usbmgmt/usbmgr/host/fdf/production/server/src/fdf.cpp
changeset 0 c9bc50fca66e
child 8 863facfed77d
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 "fdf.h"
       
    24 #include <usb/usblogger.h>
       
    25 #include "utils.h"
       
    26 #include <usbhost/internal/fdcplugin.hrh>
       
    27 #include "eventqueue.h"
       
    28 
       
    29 #ifdef __FLOG_ACTIVE
       
    30 _LIT8(KLogComponent, "fdf      ");
       
    31 #endif
       
    32 
       
    33 _LIT(KDriverUsbhubLddFileName,"usbhubdriver");
       
    34 _LIT(KDriverUsbdiLddFileName,"usbdi");
       
    35 
       
    36 PANICCATEGORY("fdf");
       
    37 
       
    38 const TUint KVendorSpecificDeviceClassValue = 0xFF;
       
    39 const TUint KVendorSpecificInterfaceClassValue = 0xFF;
       
    40 const TUint KMaxSearchKeyLength = 64; 
       
    41 
       
    42 // Factory function for TInterfaceInfo objects.
       
    43 CFdf::TInterfaceInfo* CFdf::TInterfaceInfo::NewL(RPointerArray<CFdf::TInterfaceInfo>& aInterfaces)
       
    44 	{
       
    45 	LOG_STATIC_FUNC_ENTRY
       
    46 
       
    47 	TInterfaceInfo* self = new(ELeave) TInterfaceInfo;
       
    48 	CleanupStack::PushL(self);
       
    49 	aInterfaces.AppendL(self);
       
    50 	CLEANUPSTACK_POP1(self);
       
    51 	return self;
       
    52 	}
       
    53 
       
    54 
       
    55 CFdf* CFdf::NewL()
       
    56 	{
       
    57 	LOG_STATIC_FUNC_ENTRY
       
    58 
       
    59 	CFdf* self = new(ELeave) CFdf;
       
    60 	CleanupStack::PushL(self);
       
    61 	self->ConstructL();
       
    62 	CLEANUPSTACK_POP1(self);
       
    63 	return self;
       
    64 	}
       
    65 
       
    66 CFdf::CFdf()
       
    67 :	iDevices(_FOFF(CDeviceProxy, iLink)),
       
    68 	iFunctionDrivers(_FOFF(CFdcProxy, iLink))
       
    69 	{
       
    70 	LOG_FUNC
       
    71 	}
       
    72 
       
    73 void CFdf::ConstructL()
       
    74 	{
       
    75 	LOG_FUNC
       
    76 
       
    77 #ifndef __OVER_DUMMYUSBDI__
       
    78 	// If we're using the DummyUSBDI we don't need the real USBDI.
       
    79 	TInt err = User::LoadLogicalDevice(KDriverUsbhubLddFileName);
       
    80 	if ( err != KErrAlreadyExists )
       
    81 		{
       
    82 		LEAVEIFERRORL(err);
       
    83 		}
       
    84 #endif // __OVER_DUMMYUSBDI__
       
    85 
       
    86 	LEAVEIFERRORL(iHubDriver.Open());
       
    87 
       
    88 #ifdef __OVER_DUMMYUSBDI__
       
    89 	LEAVEIFERRORL(iHubDriver.StartHost());
       
    90 #endif
       
    91 
       
    92 	iActiveWaitForBusEvent = CActiveWaitForBusEvent::NewL(iHubDriver, iBusEvent, *this);
       
    93 	iActiveWaitForBusEvent->Wait();	
       
    94 		
       
    95 	CreateFunctionDriverProxiesL();	
       
    96 	
       
    97 	iActiveWaitForEComEvent = CActiveWaitForEComEvent::NewL(*this);
       
    98 	iActiveWaitForEComEvent->Wait();
       
    99 	
       
   100 	iEventQueue = CEventQueue::NewL(*this);
       
   101 	}
       
   102 
       
   103 void CFdf::CreateFunctionDriverProxiesL()
       
   104 	{
       
   105 
       
   106 	LOG_FUNC
       
   107 	REComSession::ListImplementationsL(TUid::Uid(KFdcEcomInterfaceUid), iImplInfoArray);
       
   108 	const TUint count = iImplInfoArray.Count();
       
   109 	LOGTEXT2(_L8("\tiImplInfoArray.Count() upon FDF creation  = %d"), count);
       
   110 #ifdef __FLOG_ACTIVE
       
   111 	if ( count == 0 )
       
   112 		{
       
   113 		LOGTEXT(_L8("\tTHERE ARE NO FUNCTION DRIVERS PRESENT IN THE SYSTEM"));
       
   114 		}
       
   115 	else
       
   116 		{
       
   117 		for (TInt kk = 0; kk < count; ++kk)
       
   118 			LOGTEXT3(_L8("\t\tFDC implementation Index:%d UID: 0x%08x"), kk, iImplInfoArray[kk]->ImplementationUid());				
       
   119 		}
       
   120 #endif
       
   121 
       
   122    	for ( TUint i = 0 ; i < count ; ++i )
       
   123    		{
       
   124    		CFdcProxy* proxy = CFdcProxy::NewL(*this, *iImplInfoArray[i]);
       
   125    		
       
   126    		// If this proxy is rom based then put it in the first place
       
   127    		// this will save time when trying to load the FDC with the rule of 
       
   128    		// ROM-based ones have higher priority than installed ones.
       
   129    		if (proxy->RomBased())
       
   130    			iFunctionDrivers.AddFirst(*proxy);
       
   131    		else
       
   132    			iFunctionDrivers.AddLast(*proxy);
       
   133    		}
       
   134 	}
       
   135 
       
   136 CFdf::~CFdf()
       
   137 	{
       
   138 	LOG_FUNC
       
   139 
       
   140 	// Mimic the detachment of each attached device.
       
   141 	TSglQueIter<CDeviceProxy> deviceIter(iDevices);
       
   142 	deviceIter.SetToFirst();
       
   143 	CDeviceProxy* device;
       
   144 	while ( ( device = deviceIter++ ) != NULL )
       
   145 		{
       
   146 		const TUint deviceId = device->DeviceId();
       
   147 		LOGTEXT2(_L8("\tmimicking detachment of device with id %d"), device);
       
   148 		TellFdcsOfDeviceDetachment(deviceId);
       
   149 		iDevices.Remove(*device);
       
   150 		delete device;
       
   151 		}
       
   152 
       
   153 	// Destroy all the FDC proxies. They should each now have no 'attached
       
   154 	// devices' and no plugin instance.
       
   155 	TSglQueIter<CFdcProxy> fdcIter(iFunctionDrivers);
       
   156 	fdcIter.SetToFirst();
       
   157 	CFdcProxy* fdc;
       
   158 	while ( ( fdc = fdcIter++ ) != NULL )
       
   159 		{
       
   160 		iFunctionDrivers.Remove(*fdc);
       
   161 		delete fdc;
       
   162 		}
       
   163 
       
   164 	delete iActiveWaitForBusEvent;
       
   165 	
       
   166 	delete iActiveWaitForEComEvent;
       
   167 
       
   168 	if ( iHubDriver.Handle() )
       
   169 		{
       
   170 		iHubDriver.StopHost(); // NB this has no return value
       
   171 		}
       
   172 	iHubDriver.Close();
       
   173 
       
   174 #ifndef __OVER_DUMMYUSBDI__
       
   175 	//If we're using the DummyUSBDI the real USBDI isn't loaded.
       
   176 	TInt err = User::FreeLogicalDevice(KDriverUsbhubLddFileName);
       
   177 	LOGTEXT2(_L8("\tFreeLogicalDevice( usbhubdriver ) returned %d"), err);
       
   178 	
       
   179 	err = User::FreeLogicalDevice(KDriverUsbdiLddFileName);
       
   180 	LOGTEXT2(_L8("\tFreeLogicalDevice( usbdi ) returned %d"), err);
       
   181 #endif // __OVER_DUMMYUSBDI__
       
   182 	
       
   183 	delete iEventQueue;
       
   184 
       
   185 	// This is a worthwhile check to do at this point. If we ever don't clean
       
   186 	// up iInterfaces at the *right* time, then this will be easier to debug
       
   187 	// than a memory leak.
       
   188 	ASSERT_DEBUG(iInterfaces.Count() == 0);
       
   189 
       
   190 	iImplInfoArray.ResetAndDestroy();
       
   191 	REComSession::FinalClose();
       
   192 	}
       
   193 
       
   194 void CFdf::EnableDriverLoading()
       
   195 	{
       
   196 	LOG_FUNC
       
   197 
       
   198 	iDriverLoadingEnabled = ETrue;
       
   199 	}
       
   200 
       
   201 void CFdf::DisableDriverLoading()
       
   202 	{
       
   203 	LOG_FUNC
       
   204 
       
   205 	iDriverLoadingEnabled = EFalse;
       
   206 	}
       
   207 
       
   208 void CFdf::SetSession(CFdfSession* aSession)
       
   209 	{
       
   210 	LOG_FUNC
       
   211 	LOGTEXT2(_L8("\taSession = 0x%08x"), aSession);
       
   212 
       
   213 	iSession = aSession;
       
   214 	}
       
   215 
       
   216 CFdfSession* CFdf::Session()
       
   217 	{
       
   218 	return iSession;
       
   219 	}
       
   220 
       
   221 TBool CFdf::GetDeviceEvent(TDeviceEvent& aEvent)
       
   222 	{
       
   223 	LOG_FUNC
       
   224 
       
   225 	ASSERT_DEBUG(iEventQueue);
       
   226 	return iEventQueue->GetDeviceEvent(aEvent);
       
   227 	}
       
   228 
       
   229 TBool CFdf::GetDevmonEvent(TInt& aEvent)
       
   230 	{
       
   231 	LOG_FUNC
       
   232 
       
   233 	ASSERT_DEBUG(iEventQueue);
       
   234 	return iEventQueue->GetDevmonEvent(aEvent);
       
   235 	}
       
   236 	
       
   237 	
       
   238 // An ECom plugin has been installed or removed
       
   239 void CFdf::EComEventReceived()
       
   240 	{
       
   241 	TRAPD(ret, HandleEComEventReceivedL());
       
   242 	if (ret != KErrNone)
       
   243 		HandleDevmonEvent(KErrUsbUnableToUpdateFDProxyList);
       
   244 	
       
   245 	}
       
   246 
       
   247 void CFdf::HandleEComEventReceivedL()
       
   248 	{
       
   249 	LOG_FUNC
       
   250 	
       
   251 	// There is no way to filter ecom notification to only receive ones we are interested in, also there is no way
       
   252 	// to query ecom as to what has changed. Hence there is no option but to call ListImplementations().
       
   253 	iImplInfoArray.ResetAndDestroy();		
       
   254 			
       
   255 	REComSession::ListImplementationsL(TUid::Uid(KFdcEcomInterfaceUid), iImplInfoArray);	
       
   256 	TUint implementationsCount = iImplInfoArray.Count();
       
   257 	LOGTEXT2(_L8("\tiImplInfoArray.Count() after ECom notification= %d"), implementationsCount);
       
   258 	
       
   259 #ifdef __FLOG_ACTIVE
       
   260 	if ( implementationsCount == 0 )
       
   261 		{
       
   262 		LOGTEXT(_L8("\tTHERE ARE NO FUNCTION DRIVERS PRESENT IN THE SYSTEM"));
       
   263 		}
       
   264 		
       
   265 	TSglQueIter<CFdcProxy> proxiesIterDebug(iFunctionDrivers);
       
   266 	CFdcProxy* fdcDebug = NULL;		
       
   267 	while ( ( fdcDebug = proxiesIterDebug++ ) != NULL )
       
   268 		{
       
   269 		TUid fdcUid = fdcDebug->ImplUid();
       
   270 		LOGTEXT2(_L8("\t\tOld FDC Proxy implementation UID: 0x%08x"), fdcUid.iUid);
       
   271 		TInt fdcVersion = fdcDebug->Version();
       
   272 		LOGTEXT2(_L8("\t\tFDC Proxy version UID: %d"), fdcVersion);
       
   273 		}		
       
   274 	LOGTEXT(_L8("\t\t------------------------------------------------------------------"));
       
   275 	for (TInt kk = 0; kk < implementationsCount; ++kk)
       
   276 		{
       
   277 		TUid fdcUid2 = iImplInfoArray[kk]->ImplementationUid();
       
   278 		LOGTEXT2(_L8("\t\tNew FDC Proxy implementation UID: 0x%08x"), fdcUid2.iUid);
       
   279 		TInt fdcVersion2 = iImplInfoArray[kk]->Version();
       
   280 		LOGTEXT2(_L8("\t\tFDC Proxy version UID: %d"), fdcVersion2);					
       
   281 		}
       
   282 #endif
       
   283 
       
   284 	// See if any relevant FDCs (or upgrades) have been installed or uninstalled:	
       
   285 	
       
   286 	// For each FD in the proxy list compare the uid and version with each FD returned by ECom looking
       
   287 	// for the removal, upgrade or downgrade of an existing FD 	
       
   288 	TSglQueIter<CFdcProxy> proxiesIter(iFunctionDrivers);
       
   289 	proxiesIter.SetToFirst();
       
   290 	CFdcProxy* fdc = NULL;	
       
   291 	while ( ( fdc = proxiesIter++ ) != NULL )
       
   292 		{
       
   293 		TBool fdcRemoved = ETrue;
       
   294 		for (TInt ii = 0; ii < implementationsCount; ++ii)
       
   295 			{
       
   296 			if (fdc->ImplUid() == iImplInfoArray[ii]->ImplementationUid())
       
   297 				{			
       
   298 				// We have found an upgrade, downgrade, or duplicate (a duplicate could occur in the situation
       
   299 				// where an FD has been installed, then a device attached, then the FD uninstalled and re-installed *while*
       
   300 				// the device is still attached (meaning the FD's proxy is still in the proxy list but will have been marked
       
   301 				// for deletion when the uninstallation was detected).
       
   302 				fdcRemoved = EFalse;
       
   303 				if (fdc->Version() != iImplInfoArray[ii]->Version())
       
   304 					{
       
   305 					// We've found an upgrade or a downgrade. Note that the upgrade FD proxy needs adding to the
       
   306 					// proxy list, however that isn't done here it is done later in the loop that is searching for
       
   307 					// new FDs. This is to prevent its possible duplicate addition [consider the situation where
       
   308 					// there is FDv1 and a device is attached, then while still attached FDv2 gets installed (while will
       
   309 					// result in FDv1 getting marked for deletion), then another device is attached which will use FDv2.
       
   310 					// Now if FDv3 is installed before any of the devices were detached there will be two proxies in the 
       
   311 					// proxy list with the same UID but differing version numbers. If FDv3 is added here it will therefore
       
   312 					// be added twice].
       
   313 					if (fdc->DeviceCount())
       
   314 						{
       
   315 						// The device using the FD is still attached
       
   316 						fdc->MarkForDeletion();
       
   317 						}
       
   318 					else
       
   319 						{
       
   320 						iFunctionDrivers.Remove(*fdc);
       
   321 						delete fdc;
       
   322 						}					
       
   323 					}		
       
   324 				else
       
   325 					{
       
   326 					// we've found an FD being installed which is still currently 
       
   327 					// active in the proxy list
       
   328 					fdc->UnmarkForDeletion();
       
   329 					}	
       
   330 				// Since we found the plugin with the same implementationUid
       
   331 				// we could simply bail out to stop the looping;
       
   332 				break;
       
   333 				}
       
   334 			}
       
   335 		if (fdcRemoved)
       
   336 			{ 
       
   337 			// An FDC has been uninstalled - if the FDC isn't in use remove it 
       
   338 			// otherwise mark it for deletion
       
   339 			if (fdc->DeviceCount())
       
   340 				fdc->MarkForDeletion();
       
   341 			else
       
   342 				{
       
   343 				iFunctionDrivers.Remove(*fdc); 
       
   344 				delete fdc;				
       
   345 				}			
       
   346 			}
       
   347 		}
       
   348 		
       
   349 		
       
   350 	// For each FD returned by ECom, search and compare with the FD proxy list 
       
   351 	// looking for new FDs
       
   352 	for (TInt ii = 0; ii < implementationsCount; ++ii)
       
   353 		{
       
   354 		TBool newFdcFound = ETrue;
       
   355 		proxiesIter.SetToFirst();
       
   356 		while ( ( fdc = proxiesIter++ ) != NULL )
       
   357 			{
       
   358 			if (fdc->ImplUid() == iImplInfoArray[ii]->ImplementationUid() && fdc->Version() == iImplInfoArray[ii]->Version())
       
   359 				{
       
   360 				// No need to create a new proxy if there is one with a matching UID and version.
       
   361 				newFdcFound = EFalse;
       
   362 				
       
   363 				// We break out this loop for efficiency.
       
   364 				break;
       
   365 				}
       
   366 			}	
       
   367 			
       
   368 		if (newFdcFound)
       
   369 			{ 
       
   370 			// A new or upgrade FDC has been installed onto the device
       
   371 			CFdcProxy* proxy = CFdcProxy::NewL(*this, *iImplInfoArray[ii]);
       
   372 
       
   373 			// If this proxy is rom based then put it in the first place
       
   374 	   		// this will save time when trying to load the FDC with the rule that 
       
   375 	   		// ROM-based ones have higher priority than installed ones.
       
   376 			if (proxy->RomBased())
       
   377 				iFunctionDrivers.AddFirst(*proxy);
       
   378 			else
       
   379 				iFunctionDrivers.AddLast(*proxy);			
       
   380 			}
       
   381 		}
       
   382 	}
       
   383 
       
   384 // A bus event has occurred.
       
   385 void CFdf::MbeoBusEvent()
       
   386 	{
       
   387 	LOG_FUNC
       
   388 	LOGTEXT2(_L8("\tiBusEvent.iEventType = %d"), iBusEvent.iEventType);
       
   389 	LOGTEXT2(_L8("\tiBusEvent.iError = %d"), iBusEvent.iError);
       
   390 	LOGTEXT2(_L8("\tiBusEvent.iDeviceHandle = %d"), iBusEvent.iDeviceHandle);
       
   391 
       
   392 	switch ( iBusEvent.iEventType )
       
   393 		{
       
   394 		case RUsbHubDriver::TBusEvent::EDeviceAttached:
       
   395 			if ( !iBusEvent.iError )
       
   396 				{
       
   397 				// So far, a successful attachment.
       
   398 				HandleDeviceAttachment(iBusEvent.iDeviceHandle);
       
   399 				}
       
   400 			else
       
   401 				{
       
   402 				// It was an attachment failure. Simply tell the event queue.
       
   403 				ASSERT_DEBUG(iEventQueue);
       
   404 				iEventQueue->AttachmentFailure(iBusEvent.iError);
       
   405 				}
       
   406 			break;
       
   407 	
       
   408 		case RUsbHubDriver::TBusEvent::EDeviceRemoved:
       
   409 			// Device detachments are always 'KErrNone'. If the device was
       
   410 			// pseudo-detached due to an overcurrent condition (for instance) then
       
   411 			// the overcurrent condition is indicated through the devmon API (i.e.
       
   412 			// EDevMonEvent) and the detachment is still 'KErrNone'.
       
   413 			ASSERT_DEBUG(iBusEvent.iError == KErrNone);
       
   414 			HandleDeviceDetachment(iBusEvent.iDeviceHandle);
       
   415 			break;
       
   416 	
       
   417 		case RUsbHubDriver::TBusEvent::EDevMonEvent:
       
   418 			HandleDevmonEvent(iBusEvent.iError);
       
   419 			break;
       
   420 	
       
   421 		case RUsbHubDriver::TBusEvent::ENoEvent:
       
   422 		default:
       
   423 		break;
       
   424 		}
       
   425 
       
   426 	// Only re-post the notification when we've finished examining the
       
   427 	// TBusEvent from the previous completion. (Otherwise it might get
       
   428 	// overwritten.)
       
   429 	iActiveWaitForBusEvent->Wait();
       
   430 	}
       
   431 
       
   432 // This is the central handler for device attachment.
       
   433 // We deal with device attachments in two phases.
       
   434 // The first phase is confusingly called device attachment.
       
   435 // The second phase is driver loading.
       
   436 void CFdf::HandleDeviceAttachment(TUint aDeviceId)
       
   437 	{
       
   438 	LOG_FUNC
       
   439 	// This is filled in by HandleDeviceAttachmentL on success.
       
   440 	CDeviceProxy* device;
       
   441 	TRAPD(err, HandleDeviceAttachmentL(aDeviceId, device));
       
   442 	if ( err )
       
   443 		{
       
   444 		LOGTEXT2(_L8("\terr = %d"), err);
       
   445 		// There was an attachment failure, so we just increment the count of
       
   446 		// attachment failures.
       
   447 		ASSERT_DEBUG(iEventQueue);
       
   448 		iEventQueue->AttachmentFailure(err);
       
   449 		// If we failed the attachment phase, we can't try to load drivers for
       
   450 		// the device.
       
   451 
       
   452 		}
       
   453 	else
       
   454 		{
       
   455 		// This function always moves the 'driver loading' event from the
       
   456 		// device proxy created by HandleDeviceAttachmentL to the event queue.
       
   457 		// This event object is always populated with the correct status and
       
   458 		// error.
       
   459 		ASSERT_DEBUG(device);
       
   460 		DoDriverLoading(*device);
       
   461 		}
       
   462 
       
   463 	// Finally, clean up the collection of information on the device's
       
   464 	// interfaces which was populated (maybe only partly) in
       
   465 	// HandleDeviceAttachmentL.
       
   466 	iCurrentDevice = NULL;
       
   467 	iInterfaces.ResetAndDestroy();
       
   468 	}
       
   469 
       
   470 // This does the 'device attachment' phase of the new device attachment only.
       
   471 void CFdf::HandleDeviceAttachmentL(TUint aDeviceId, CDeviceProxy*& aDevice)
       
   472 	{
       
   473 	LOG_FUNC
       
   474 
       
   475 	// Create the device proxy
       
   476 	aDevice = CDeviceProxy::NewL(iHubDriver, aDeviceId);
       
   477 	CleanupStack::PushL(aDevice);
       
   478 	iCurrentDevice = aDevice;
       
   479 	// Get necessary descriptors (for this phase)
       
   480 	LEAVEIFERRORL(aDevice->GetDeviceDescriptor(iDD));
       
   481 	LOGTEXT2(_L8("\tiDD.USBBcd = 0x%04x"), iDD.USBBcd());
       
   482 	LOGTEXT2(_L8("\tiDD.DeviceClass = 0x%02x"), iDD.DeviceClass());
       
   483 	LOGTEXT2(_L8("\tiDD.DeviceSubClass = 0x%02x"), iDD.DeviceSubClass());
       
   484 	LOGTEXT2(_L8("\tiDD.DeviceProtocol = 0x%02x"), iDD.DeviceProtocol());
       
   485 	LOGTEXT2(_L8("\tiDD.MaxPacketSize0 = %d"), iDD.MaxPacketSize0());
       
   486 	LOGTEXT2(_L8("\tiDD.VendorId = 0x%04x"), iDD.VendorId());
       
   487 	LOGTEXT2(_L8("\tiDD.ProductId = 0x%04x"), iDD.ProductId());
       
   488 	LOGTEXT2(_L8("\tiDD.DeviceBcd = 0x%04x"), iDD.DeviceBcd());
       
   489 	LOGTEXT2(_L8("\tiDD.ManufacturerIndex = %d"), iDD.ManufacturerIndex());
       
   490 	LOGTEXT2(_L8("\tiDD.ProductIndex = %d"), iDD.ProductIndex());
       
   491 	LOGTEXT2(_L8("\tiDD.SerialNumberIndex = %d"), iDD.SerialNumberIndex());
       
   492 	LOGTEXT2(_L8("\tiDD.NumConfigurations = %d"), iDD.NumConfigurations());
       
   493 	LEAVEIFERRORL(aDevice->GetConfigurationDescriptor(iCD));
       
   494 	LOGTEXT2(_L8("\tiCD.TotalLength = %d"), iCD.TotalLength());
       
   495 	LOGTEXT2(_L8("\tiCD.NumInterfaces = %d"), iCD.NumInterfaces());
       
   496 	LOGTEXT2(_L8("\tiCD.ConfigurationValue = %d"), iCD.ConfigurationValue());
       
   497 	LOGTEXT2(_L8("\tiCD.ConfigurationIndex = %d"), iCD.ConfigurationIndex());
       
   498 	LOGTEXT2(_L8("\tiCD.Attributes = %d"), iCD.Attributes());
       
   499 	LOGTEXT2(_L8("\tiCD.MaxPower = %d"), iCD.MaxPower());
       
   500 
       
   501 	const TUint8 numberOfInterfaces = iCD.NumInterfaces();
       
   502 	LOGTEXT2(_L8("\tnumberOfInterfaces (field in config descriptor) = %d)"), numberOfInterfaces);
       
   503 	if ( numberOfInterfaces == 0 )
       
   504 		{
       
   505 		LEAVEL(KErrUsbConfigurationHasNoInterfaces);
       
   506 		}
       
   507 
       
   508 	// Walk the configuration bundle. Collect information on each interface
       
   509 	// (its number, class, subclass and protocol). This populates iInterfaces.
       
   510 	ASSERT_DEBUG(iInterfaces.Count() == 0);
       
   511 	ASSERT_ALWAYS(iCurrentDevice);
       
   512 	ParseL(iCD);
       
   513 
       
   514 	// Log iInterfaces.
       
   515 	const TUint interfaceCount = iInterfaces.Count();
       
   516 	LOGTEXT2(_L8("\tinterfaceCount (parsed from bundle) = %d"), interfaceCount);
       
   517 #ifdef __FLOG_ACTIVE
       
   518 	LOGTEXT(_L8("\tLogging iInterfaces:"));
       
   519 	for ( TUint ii = 0 ; ii < interfaceCount ; ++ii )
       
   520 		{
       
   521 		const TInterfaceInfo* ifInfo = iInterfaces[ii];
       
   522 		ASSERT_DEBUG(ifInfo);
       
   523 		LOGTEXT6(_L8("\t\tiInterfaces[%d]: number %d, interface class 0x%02x subclass 0x%02x protocol 0x%02x"),
       
   524 			ii,
       
   525 			ifInfo->iNumber,
       
   526 			ifInfo->iClass,
       
   527 			ifInfo->iSubclass,
       
   528 			ifInfo->iProtocol
       
   529 			);
       
   530 		}
       
   531 #endif
       
   532 
       
   533 	// Check that the config's NumInterfaces is the same as the actual number
       
   534 	// of interface descriptors we found. We rely on this later on.
       
   535 	if ( numberOfInterfaces != interfaceCount )
       
   536 		{
       
   537 		LEAVEL(KErrUsbInterfaceCountMismatch);
       
   538 		}
       
   539 
       
   540 	// Check that each interface number in iInterfaces is unique.
       
   541 	if ( interfaceCount > 1 )
       
   542 		{
       
   543 		for ( TUint ii = 0 ; ii < interfaceCount ; ++ii )
       
   544 			{
       
   545 			const TInterfaceInfo* lhs = iInterfaces[ii];
       
   546 			ASSERT_DEBUG(lhs);
       
   547 			for ( TUint jj = ii+1 ; jj < interfaceCount ; ++jj )
       
   548 				{
       
   549 				const TInterfaceInfo* rhs = iInterfaces[jj];
       
   550 				ASSERT_DEBUG(rhs);
       
   551 				if ( lhs->iNumber == rhs->iNumber )
       
   552 					{
       
   553 					LEAVEL(KErrUsbDuplicateInterfaceNumbers);
       
   554 					}
       
   555 				}
       
   556 			}
       
   557 		}
       
   558 
       
   559 #ifndef __OVER_DUMMYUSBDI__
       
   560 	// If we're using the DummyUSBDI we don't need the real USBDI.
       
   561 	// Load USBDI when attached devices goes from 0 to 1
       
   562 	if (iDevices.IsEmpty())
       
   563 		{
       
   564 		TInt err = User::LoadLogicalDevice(KDriverUsbdiLddFileName);
       
   565 		if ( err != KErrAlreadyExists )
       
   566 			{
       
   567 			LEAVEIFERRORL(err);
       
   568 			}
       
   569 		}
       
   570 #endif // __OVER_DUMMYUSBDI__
       
   571 	
       
   572 	// Now we know we've succeeded with a device attachment, remove the device
       
   573 	// proxy from the cleanup stack and put it on the TSglQue.
       
   574 	CLEANUPSTACK_POP1(aDevice);
       
   575 	iDevices.AddLast(*aDevice);
       
   576 	// Also put an event on the event queue.
       
   577 	TDeviceEvent* const attachmentEvent = aDevice->GetAttachmentEventObject();
       
   578 	ASSERT_DEBUG(attachmentEvent);
       
   579 	attachmentEvent->iInfo.iVid = iDD.VendorId();
       
   580 	attachmentEvent->iInfo.iPid = iDD.ProductId();
       
   581 	attachmentEvent->iInfo.iError = KErrNone;
       
   582 	ASSERT_DEBUG(iEventQueue);
       
   583 	iEventQueue->AddDeviceEvent(*attachmentEvent);
       
   584 	LOGTEXT2(_L8("***USB HOST STACK: SUCCESSFUL ATTACHMENT OF DEVICE (id %d)"), aDeviceId);
       
   585 	}
       
   586 
       
   587 void CFdf::DoDriverLoading(CDeviceProxy& aDevice)
       
   588 	{
       
   589 	LOG_FUNC
       
   590 
       
   591 	// Leaving or returning from DoDriverLoadingL is the trigger to put the
       
   592 	// 'driver loading' event object on the event queue. It must already have
       
   593 	// been populated correctly (the actual error code it left with doesn't
       
   594 	// feed into the driver loading event).
       
   595 	TRAP_IGNORE(DoDriverLoadingL(aDevice));
       
   596 	
       
   597 	TDeviceEvent* const driverLoadingEvent = aDevice.GetDriverLoadingEventObject();
       
   598 	ASSERT_DEBUG(driverLoadingEvent);
       
   599 	// The driver loading event object says whether driver loading succeeded
       
   600 	// (all interfaces were claimed without error), partly succeeded (not all
       
   601 	// interfaces were claimed without error), or failed (no interfaces were
       
   602 	// claimed without error). This information is intended for USBMAN so it
       
   603 	// can tell the user, but we also use it now to suspend the device if
       
   604 	// driver loading failed completely.
       
   605 	if ( driverLoadingEvent->iInfo.iDriverLoadStatus == EDriverLoadFailure )
       
   606 		{
       
   607 		// We can't do anything with error here. Suspending the device is for
       
   608 		// power-saving reasons and is not critical.
       
   609 		(void)aDevice.Suspend();
       
   610 		}
       
   611 	ASSERT_DEBUG(iEventQueue);
       
   612 	iEventQueue->AddDeviceEvent(*driverLoadingEvent);
       
   613 	}
       
   614 
       
   615 
       
   616 void CFdf::DoDriverLoadingL(CDeviceProxy& aDevice)
       
   617 	{
       
   618 	LOG_FUNC
       
   619 
       
   620 	// Check whether driver loading is enabled.
       
   621 	if ( !iDriverLoadingEnabled )
       
   622 		{
       
   623 		// Complete driver load failure scenario.
       
   624 		aDevice.SetDriverLoadingEventData(EDriverLoadFailure, KErrUsbDriverLoadingDisabled);
       
   625 		LEAVEL(KErrGeneral);
       
   626 	}
       
   627 
       
   628 
       
   629 	// Set this member up so that when the FDC calls TokenForInterface we call
       
   630 	// the right proxy object.
       
   631 
       
   632 	TInt collectedErr = KErrNone;
       
   633 	TBool anySuccess = EFalse;
       
   634 
       
   635 
       
   636 	// Now actually try to load the drivers.
       
   637 	// Device drivers are located based upon descriptor information from the USB device. The first search is
       
   638 	// based on information from the device descriptor and looks for a driver that matches the whole device; 
       
   639 	// the second search is based upon locating a driver for each interface within a configuration.
       
   640 	// The particular keys used in the driver search are defined in the Universal Serial Bus Common Class
       
   641 	// Specification version 1.0. They are represented by TDeviceSearchKeys and TInterfaceSearchKeys.						
       
   642 	//
       
   643 	// First perform a device search by iterating through the keys in TDeviceSearchKeys looking for a matching driver.
       
   644 	TBool functionDriverFound = SearchForADeviceFunctionDriverL(aDevice, anySuccess, collectedErr);
       
   645 	
       
   646 	// When do the parsing against the CD bundle, we already know if there is IAD(Interface Association Descriptor)
       
   647 	// in the new attached device. Once we finished the device level searching of FDC and we couldn't find any, we
       
   648 	// break down the loading process
       
   649 	if (aDevice.HasIADFlag() && !functionDriverFound)
       
   650 		{
       
   651 		aDevice.SetDriverLoadingEventData(EDriverLoadFailure, KErrUsbUnsupportedDevice);
       
   652 		LEAVEL(KErrGeneral);		
       
   653 		}
       
   654 	// If a device FD is found then it is supposed to claim all the interfaces, if it didn't then report
       
   655 	// a partial success but don't offer unclaimed interfaces to any other FD.
       
   656 	const TUint interfaceCount = iInterfaces.Count();
       
   657 
       
   658 
       
   659 	
       
   660 	// If no device driver was found then next perform an Interface search
       
   661 	if (!functionDriverFound)
       
   662 		SearchForInterfaceFunctionDriversL(aDevice, anySuccess, collectedErr);
       
   663 
       
   664 	// Now worry about the following:
       
   665 	// (a) are there any unclaimed interfaces remaining?
       
   666 	// (b) what's in collectedErr?
       
   667 	// Whether all interfaces were taken, some, or none, collectedErr may have
       
   668 	// an error in it or KErrNone. We use specific error codes in some cases.			
       
   669 	TUint unclaimedInterfaces = UnclaimedInterfaceCount();
       
   670 	LOGTEXT2(_L8("\tunclaimedInterfaces = %d"), unclaimedInterfaces);
       
   671 	LOGTEXT2(_L8("\tanySuccess = %d"), anySuccess);
       
   672 	LOGTEXT2(_L8("\tcollectedErr = %d"), collectedErr);
       
   673 	ASSERT_DEBUG(unclaimedInterfaces <= interfaceCount);
       
   674 
       
   675 	if(iDeviceDetachedTooEarly)
       
   676 		{
       
   677 		LOGTEXT(_L8("\tDevice has been detached too early!"));
       
   678 		iDeviceDetachedTooEarly = EFalse;
       
   679 		// the choice of having the status to be EDriverLoadPartialSuccess
       
   680 		// was not to clash with trying to suspend the device because
       
   681 		// of a total failure to load the FD.(because device is detached)
       
   682 		// even though that a FDC has been created
       
   683 		// see the :
       
   684 		// if ( driverLoadingEvent->iInfo.iDriverLoadStatus == EDriverLoadFailure )
       
   685 		// in function above => void CFdf::DoDriverLoadingL(etc...)
       
   686 		aDevice.SetDriverLoadingEventData(EDriverLoadPartialSuccess, KErrUsbDeviceDetachedDuringDriverLoading);
       
   687 		}
       
   688 	else
       
   689 		{
       
   690 		SetFailureStatus(unclaimedInterfaces, interfaceCount, anySuccess, collectedErr, aDevice);
       
   691 		}// iDeviceDetachedTooEarly
       
   692 
       
   693 	}
       
   694 
       
   695 // Recursive function, originally called with the configuration descriptor.
       
   696 // Builds up information on the interface descriptors in the configuration
       
   697 // bundle.
       
   698 void CFdf::ParseL(TUsbGenericDescriptor& aDesc)
       
   699 	{
       
   700 	LOG_FUNC
       
   701 	LOGTEXT2(_L8("\t&aDesc = 0x%08x"), &aDesc);
       
   702 	LOGTEXT2(_L8("\taDesc.ibDescriptorType = %d"), aDesc.ibDescriptorType);
       
   703 	LOGTEXT2(_L8("\taDesc.iFirstChild = 0x%08x"), aDesc.iFirstChild);
       
   704 	LOGTEXT2(_L8("\taDesc.iNextPeer = 0x%08x"), aDesc.iNextPeer);
       
   705 
       
   706 	if ( aDesc.ibDescriptorType == EInterface )
       
   707 		{
       
   708 		// Add interface information to collection, but only if it's alternate
       
   709 		// setting 0.
       
   710 		const TUsbInterfaceDescriptor& ifDesc = static_cast<TUsbInterfaceDescriptor&>(aDesc);
       
   711 		if ( ifDesc.AlternateSetting() == 0 ) // hard-coded '0' means the default (initial configuration) setting
       
   712 			{
       
   713 			LOGTEXT2(_L8("\tifDesc.InterfaceNumber = %d"), ifDesc.InterfaceNumber());
       
   714 			LOGTEXT2(_L8("\tifDesc.NumEndpoints = %d"), ifDesc.NumEndpoints());
       
   715 			LOGTEXT2(_L8("\tifDesc.InterfaceClass = 0x%02x"), ifDesc.InterfaceClass());
       
   716 			LOGTEXT2(_L8("\tifDesc.InterfaceSubClass = 0x%02x"), ifDesc.InterfaceSubClass());
       
   717 			LOGTEXT2(_L8("\tifDesc.InterfaceProtocol = 0x%02x"), ifDesc.InterfaceProtocol());
       
   718 			LOGTEXT2(_L8("\tifDesc.Interface = %d"), ifDesc.Interface());
       
   719 
       
   720 			TInterfaceInfo* ifInfo = TInterfaceInfo::NewL(iInterfaces);
       
   721 			ifInfo->iNumber = ifDesc.InterfaceNumber();
       
   722 			ifInfo->iClass = ifDesc.InterfaceClass();
       
   723 			ifInfo->iSubclass = ifDesc.InterfaceSubClass();
       
   724 			ifInfo->iProtocol = ifDesc.InterfaceProtocol();
       
   725 			ifInfo->iClaimed = EFalse;
       
   726 			}
       
   727 		}
       
   728 	else if (!iCurrentDevice->HasIADFlag() && aDesc.ibDescriptorType == EInterfaceAssociation)
       
   729 		{
       
   730 		// When found a Interface association descriptor, set this flag to ETrue,
       
   731 		// it is checked later after the device level driverloading.
       
   732 		iCurrentDevice->SetHasIADFlag();
       
   733 		}
       
   734 	else if (aDesc.ibDescriptorType == EOTG)
       
   735 		{
       
   736 		// OTG descriptor found
       
   737 		const TUsbOTGDescriptor& otgDesc = static_cast<TUsbOTGDescriptor&>(aDesc);
       
   738 
       
   739 		LOGTEXT2(_L8("\totgDesc.Attributes = %b"), otgDesc.Attributes());
       
   740 		LOGTEXT2(_L8("\totgDesc.HNPSupported = %d"), otgDesc.HNPSupported());
       
   741 		LOGTEXT2(_L8("\totgDesc.SRPSupported = %d"), otgDesc.SRPSupported());
       
   742 		
       
   743 		iCurrentDevice->SetOtgDescriptorL(otgDesc);
       
   744 		}
       
   745 
       
   746 	TUsbGenericDescriptor* const firstChild = aDesc.iFirstChild;
       
   747 	if ( firstChild )
       
   748 		{
       
   749 		ParseL(*firstChild);
       
   750 		}
       
   751 
       
   752 	TUsbGenericDescriptor* const nextPeer = aDesc.iNextPeer;
       
   753 	if ( nextPeer )
       
   754 		{
       
   755 		ParseL(*nextPeer);
       
   756 		}
       
   757 	}
       
   758 
       
   759 // Method that uses only one array to hold the unclaimed interface numbers.
       
   760 void CFdf::FindDriversForInterfacesUsingSpecificKeyL(CDeviceProxy& aDevice,
       
   761 													TInt& aCollectedErr,
       
   762 													TBool& aAnySuccess,			
       
   763 													RArray<TUint>& aInterfacesNumberArray, 
       
   764 													TInterfaceSearchKeys aKey)	
       
   765 	{
       
   766 	LOG_FUNC
       
   767 
       
   768 	const TUint interfaceCount = iInterfaces.Count();
       
   769 	for ( TUint ii = 0 ; ii < interfaceCount ; ++ii )
       
   770 		{
       
   771 		TInterfaceInfo* ifInfo = iInterfaces[ii];		
       
   772 		ASSERT_DEBUG(ifInfo);
       
   773 		
       
   774 		if ((ifInfo->iClaimed) ||
       
   775 			(aKey == EVendorInterfacesubclassInterfaceprotocol && ifInfo->iClass != KVendorSpecificInterfaceClassValue)||	
       
   776 			(aKey == EVendorInterfacesubclass && ifInfo->iClass != KVendorSpecificInterfaceClassValue) ||
       
   777 			(aKey == EInterfaceclassInterfacesubclassInterfaceprotocol && ifInfo->iClass == KVendorSpecificInterfaceClassValue) ||
       
   778 			(aKey == EInterfaceclassInterfacesubclass && ifInfo->iClass == KVendorSpecificInterfaceClassValue))
       
   779 			{
       
   780 			continue;
       
   781 			}
       
   782 		
       
   783 
       
   784 		TBuf8<KMaxSearchKeyLength> searchKey;
       
   785 		FormatInterfaceSearchKey(searchKey, aKey, *ifInfo);
       
   786 
       
   787 		LOGTEXT2(_L8("\tsearchKey = \"%S\""), &searchKey);
       
   788 		// RArray<TUint>* array = &aInterfacesNumberArray;
       
   789 
       
   790 		FindDriverForInterfaceUsingSpecificKey(aDevice, aCollectedErr, aAnySuccess, aInterfacesNumberArray, searchKey);
       
   791 
       
   792 		// Putting ii+1 as the starting offset is to remove the interface on which
       
   793 		// the searching have been done.		
       
   794 		RebuildUnClaimedInterfacesArrayL(aDevice, aInterfacesNumberArray, ii+1);
       
   795 		}
       
   796 	}
       
   797 
       
   798 
       
   799 
       
   800 // Called for one interface, to find a Function Driver on the basis of a
       
   801 
       
   802 // specific search key.
       
   803 void CFdf::FindDriverForInterfaceUsingSpecificKey(CDeviceProxy& aDevice,
       
   804 								   TInt& aCollectedErr,
       
   805 								   TBool& aAnySuccess,
       
   806 								   RArray<TUint>& aInterfacesGivenToFdc,
       
   807 								   const TDesC8& aSearchKey)
       
   808 	{
       
   809 
       
   810 	LOG_FUNC
       
   811 	LOGTEXT2(_L8("\taSearchKey = \"%S\""), &aSearchKey);
       
   812 
       
   813 	// Find an FDC matching this search key.
       
   814 	TSglQueIter<CFdcProxy> iter(iFunctionDrivers);
       
   815 	iter.SetToFirst();
       
   816 	CFdcProxy* fdc;
       
   817 
       
   818 	while ( ( fdc = iter++ ) != NULL )
       
   819 		{
       
   820 		LOGTEXT2(_L8("\tFDC's default_data field = \"%S\""), &fdc->DefaultDataField());
       
   821 #ifdef _DEBUG
       
   822 	// having these two together in the debug window is helpful for interactive debugging
       
   823 	TBuf8<KMaxSearchKeyLength > fd_key;
       
   824 	fd_key.Append(fdc->DefaultDataField().Ptr(), fdc->DefaultDataField().Length() > KMaxSearchKeyLength ? KMaxSearchKeyLength : fdc->DefaultDataField().Length());
       
   825 	TBuf8<KMaxSearchKeyLength > searchKey;
       
   826 	searchKey.Append(aSearchKey.Ptr(), aSearchKey.Length() > KMaxSearchKeyLength ? KMaxSearchKeyLength : aSearchKey.Length());
       
   827 	TInt version = fdc->Version();
       
   828 #endif // _DEBUG
       
   829 		if (aSearchKey.CompareF(fdc->DefaultDataField()) == 0 && !fdc->MarkedForDeletion())
       
   830 			{
       
   831 			// If there is more than one matching FD then if all of them are in RAM we simply choose the first one we find.
       
   832 			// (Similarly if they are all in ROM we choose the first one although this situation should not arise as a device
       
   833 			// manufacturer should not put two matching FDs into ROM).
       
   834 			// However if there are matching FDs in ROM and RAM then the one in ROM should be selected in preference to
       
   835 			// any in RAM. Hence at this point if the matching FD we have found is in RAM then we need to scan the list
       
   836 			// of FDs to see if there is also a matching one in ROM and if so we'll skip this iteration of the loop.
       
   837 			
       
   838 			// Edwin comment
       
   839 			// Put the searching key and the iterator as the parameter of 
       
   840 			// searching if more FDCs have the same default_data. The iterator
       
   841 			// helps to searching from the current FDC since this is the very first
       
   842 			// suitable FDC we found so fa.
       
   843 			if (!aDevice.MultipleDriversFlag() && FindMultipleFDs(aSearchKey, iter))
       
   844 				{
       
   845 				aDevice.SetMultipleDriversFlag();
       
   846 				}
       
   847 			
       
   848 			LOGTEXT2(_L8("\tfound matching FDC (0x%08x)"), fdc);
       
   849 #ifdef __FLOG_ACTIVE
       
   850 			const TUint count = aInterfacesGivenToFdc.Count();
       
   851 			LOGTEXT2(_L8("\tlogging aInterfacesGivenToFdc (interfaces being offered to the FDC): count = %d"), count);
       
   852 			for ( TUint ii = 0 ; ii < count ; ++ii )
       
   853 				{
       
   854 				LOGTEXT3(_L8("\t\tindex %d: interface number %d"), ii, aInterfacesGivenToFdc[ii]);
       
   855 				}
       
   856 #endif
       
   857 			TInt err = fdc->NewFunction(aDevice.DeviceId(), aInterfacesGivenToFdc, iDD, iCD);
       
   858 			LOGTEXT2(_L8("\tNewFunction returned %d"), err);
       
   859 			// To correctly determine whether the driver load for the whole
       
   860 			// configuration was a complete failure, a partial success or a
       
   861 			// complete success, we need to collect any non-KErrNone error
       
   862 			// from this, and whether any handovers worked at all.
       
   863 			if ( err == KErrNone )
       
   864 				{
       
   865 #ifdef __FLOG_ACTIVE
       
   866 				LOGTEXT3(_L8("***USB HOST STACK: THE FOLLOWING INTERFACES OF DEVICE %d WERE SUCCESSFULLY PASSED TO FUNCTION DRIVER WITH IMPL UID 0x%08x"),
       
   867 					aDevice.DeviceId(), fdc->ImplUid());
       
   868 				// We want to log each interface that's in
       
   869 				// aInterfacesGivenToFdc AND is marked claimed in iInterfaces.
       
   870 				for ( TUint ii = 0 ; ii < aInterfacesGivenToFdc.Count() ; ++ii )
       
   871 					{
       
   872 					const TUint ifNum = aInterfacesGivenToFdc[ii];
       
   873 					for ( TUint jj = 0 ; jj < iInterfaces.Count() ; ++jj )
       
   874 						{
       
   875 						const TInterfaceInfo* ifInfo = iInterfaces[jj];
       
   876 						ASSERT_DEBUG(ifInfo);
       
   877 						if (	ifNum == ifInfo->iNumber
       
   878 							&&	ifInfo->iClaimed
       
   879 							)
       
   880 							{
       
   881 							LOGTEXT2(_L8("***USB HOST STACK: bInterfaceNumber %d"), ifNum);
       
   882 							}
       
   883 						}
       
   884 					}
       
   885 #endif
       
   886 				aAnySuccess = ETrue;
       
   887 				}
       
   888 			else
       
   889 				{
       
   890 				aCollectedErr = err;
       
   891 				}
       
   892 			// We found a matching FDC for this interface- no need to look for more.
       
   893 			break;
       
   894 			}
       
   895 		}
       
   896 	}
       
   897 
       
   898 void CFdf::HandleDeviceDetachment(TUint aDeviceId)
       
   899 	{
       
   900 	LOG_FUNC
       
   901 	LOGTEXT2(_L8("\taDeviceId = %d"), aDeviceId);
       
   902 
       
   903 
       
   904 #ifdef _DEBUG
       
   905 	TBool found = EFalse;
       
   906 #endif
       
   907 	// Find the relevant device proxy. If there isn't one, just drop the
       
   908 	// notification, assuming that the corresponding attachment failed at the
       
   909 	// FDF level.
       
   910 	TSglQueIter<CDeviceProxy> iter(iDevices);
       
   911 	iter.SetToFirst();
       
   912 	CDeviceProxy* device;
       
   913 	while ( ( device = iter++ ) != NULL )
       
   914 		{
       
   915 		if ( device->DeviceId() == aDeviceId )
       
   916 			{
       
   917 #ifdef _DEBUG
       
   918 			found = ETrue;
       
   919 #endif
       
   920 			LOGTEXT(_L8("\tfound matching device proxy"));
       
   921 
       
   922 			iDevices.Remove(*device);
       
   923 			// Before destroying the device proxy, take the detachment event
       
   924 			// stored in it for the event queue.
       
   925 			TDeviceEvent* const detachmentEvent = device->GetDetachmentEventObject();
       
   926 			ASSERT_DEBUG(detachmentEvent);
       
   927 			ASSERT_DEBUG(iEventQueue);
       
   928 			iEventQueue->AddDeviceEvent(*detachmentEvent);
       
   929 			LOGTEXT2(_L8("***USB HOST STACK: DETACHMENT OF DEVICE (id %d)"), aDeviceId);
       
   930 			delete device;
       
   931 
       
   932 			TellFdcsOfDeviceDetachment(aDeviceId);
       
   933 			
       
   934 #ifndef __OVER_DUMMYUSBDI__
       
   935 			// If we're using the DummyUSBDI the real USBDI isn't loaded.
       
   936 			// Unload USBDI when attached devices goes from 1 to 0
       
   937 			if (iDevices.IsEmpty())
       
   938 				{
       
   939 				TInt err = User::FreeLogicalDevice(KDriverUsbdiLddFileName);
       
   940 				LOGTEXT2(_L8("\tFreeLogicalDevice( usbdi ) returned %d"), err);
       
   941 				}
       
   942 #endif // __OVER_DUMMYUSBDI__
       
   943 			
       
   944 			break;
       
   945 			}
       
   946 		}
       
   947 
       
   948 #ifdef _DEBUG
       
   949 	if ( !found )
       
   950 		{
       
   951 		LOGTEXT(_L8("\tno matching device proxy found"));
       
   952 		}
       
   953 #endif
       
   954 	}
       
   955 
       
   956 void CFdf::HandleDevmonEvent(TInt aEvent)
       
   957 	{
       
   958 	LOG_FUNC
       
   959 	LOGTEXT2(_L8("\taEvent = %d"), aEvent);
       
   960 
       
   961 	ASSERT_DEBUG(iEventQueue);
       
   962 	iEventQueue->AddDevmonEvent(aEvent);
       
   963 	}
       
   964 
       
   965 void CFdf::TellFdcsOfDeviceDetachment(TUint aDeviceId)
       
   966 	{
       
   967 	LOG_FUNC
       
   968 	LOGTEXT2(_L8("\taDeviceId = %d"), aDeviceId);
       
   969 
       
   970 	TSglQueIter<CFdcProxy> iter(iFunctionDrivers);
       
   971 	iter.SetToFirst();
       
   972 	CFdcProxy* fdc;
       
   973 	while ( ( fdc = iter++ ) != NULL )
       
   974 		{
       
   975 		fdc->DeviceDetached(aDeviceId);
       
   976 		if (fdc->DeviceCount() == 0 && fdc->MarkedForDeletion())
       
   977 			{ // If the FDC was uninstalled while it was in use then it couldn't be deleted at that point so delete it now
       
   978 			iFunctionDrivers.Remove(*fdc);
       
   979 			delete fdc;
       
   980 			}
       
   981 		}			
       
   982 		
       
   983 	}
       
   984 
       
   985 TUint32 CFdf::TokenForInterface(TUint8 aInterface)
       
   986 	{
       
   987 	LOG_FUNC
       
   988 	LOGTEXT2(_L8("\taInterface = %d"), aInterface);
       
   989 	TUint32 token = 0;
       
   990 
       
   991 	// Check that the interface was in the array given to the FD and mark it
       
   992 	// as claimed.
       
   993 	TBool found = EFalse;
       
   994 	const TUint interfaceCount = iInterfaces.Count();
       
   995 	for ( TUint ii = 0 ; ii < interfaceCount ; ++ii )
       
   996 		{
       
   997 		TInterfaceInfo* ifInfo = iInterfaces[ii];
       
   998 		ASSERT_DEBUG(ifInfo);
       
   999 		if ( ifInfo->iNumber == aInterface )
       
  1000 			{
       
  1001 			found = ETrue;
       
  1002 			// The FDC tried to claim an interface that was already claimed.
       
  1003 			ASSERT_ALWAYS(!ifInfo->iClaimed);
       
  1004 			ifInfo->iClaimed = ETrue;
       
  1005 			break;
       
  1006 			}
       
  1007 		}
       
  1008 	// Could not find interface in the interface array- the FDC tried to claim
       
  1009 	// an interface it had not been offered.
       
  1010 	ASSERT_ALWAYS(found);
       
  1011 
       
  1012 	ASSERT_DEBUG(iCurrentDevice);
       
  1013 
       
  1014 	// GetTokenForInterface will return error in the following cases:
       
  1015 	// 1/ KErrBadHandle: invalid device handle (the CDeviceProxy asserts that
       
  1016 	// the handle is valid) because the device has been detached while processing
       
  1017 	// may be due to too much current or cable has been removed
       
  1018 	// so FDF will still return a token of 0 and FDF will handle the proper
       
  1019 	// device detachment when it will be able to process the detachment notification
       
  1020 	//
       
  1021 	// 2/ KErrNotFound: interface not found (if this happens, the FDC has
       
  1022 	// misbehaved, and the correct thing to do is to panic)
       
  1023 	// 3/ KErrInUse: we've already requested a token for that interface
       
  1024 	// (ditto)
       
  1025 	// 4/ KErrOverflow: when 0xFFFFFFFF tokens have been requested (this is a
       
  1026 	// realistic built-in limitation of USBD)
       
  1027 
       
  1028 
       
  1029 	TInt err = iCurrentDevice->GetTokenForInterface(aInterface, token);
       
  1030 	switch(err)
       
  1031 		{
       
  1032 		case KErrBadHandle:
       
  1033 			token = 0;
       
  1034 			iDeviceDetachedTooEarly = ETrue;
       
  1035 
       
  1036 		case KErrNone: // Fall through and do nothing
       
  1037 			break;
       
  1038 
       
  1039 		default:
       
  1040 			LOGTEXT3(_L8("\tUnexpected error %d when requesting token for aInterface %d"),err,aInterface);
       
  1041 			ASSERT_ALWAYS(0);
       
  1042 			break;
       
  1043 		}
       
  1044 
       
  1045 	LOGTEXT3(_L8("\tToken for interface %d is = %d"),aInterface, token);
       
  1046 
       
  1047 	return token;
       
  1048 	}
       
  1049 
       
  1050 CDeviceProxy* CFdf::DeviceProxyL(TUint aDeviceId) const
       
  1051 	{
       
  1052 	LOG_FUNC
       
  1053 	LOGTEXT2(_L8("\taDeviceId = %d"), aDeviceId);
       
  1054 
       
  1055 	TSglQueIter<CDeviceProxy> iter(const_cast<CFdf*>(this)->iDevices);
       
  1056 	iter.SetToFirst();
       
  1057 	CDeviceProxy* device = NULL;
       
  1058 	while ( ( device = iter++ ) != NULL )
       
  1059 		{
       
  1060 		if ( device->DeviceId() == aDeviceId )
       
  1061 			{
       
  1062 			LOGTEXT2(_L8("\tdevice = 0x%08x"), device);
       
  1063 			return device;
       
  1064 			}
       
  1065 		}
       
  1066 	LEAVEL(KErrNotFound);
       
  1067 	return NULL; // avoid warning
       
  1068 	}
       
  1069 
       
  1070 const RArray<TUint>& CFdf::GetSupportedLanguagesL(TUint aDeviceId) const
       
  1071 	{
       
  1072 	LOG_FUNC
       
  1073 	LOGTEXT2(_L8("\taDeviceId = %d"), aDeviceId);
       
  1074 
       
  1075 	CDeviceProxy* deviceProxy = DeviceProxyL(aDeviceId);
       
  1076 	return deviceProxy->GetSupportedLanguages();
       
  1077 	}
       
  1078 
       
  1079 void CFdf::GetManufacturerStringDescriptorL(TUint aDeviceId, TUint32 aLangId, TName& aString) const
       
  1080 	{
       
  1081 	LOG_FUNC
       
  1082 	LOGTEXT3(_L8("\taDeviceId = %d, aLangId = 0x%04x"), aDeviceId, aLangId);
       
  1083 
       
  1084 	CDeviceProxy* deviceProxy = DeviceProxyL(aDeviceId);
       
  1085 	deviceProxy->GetManufacturerStringDescriptorL(aLangId, aString);
       
  1086 	LOGTEXT2(_L("\taString = \"%S\""), &aString);
       
  1087 	}
       
  1088 
       
  1089 void CFdf::GetProductStringDescriptorL(TUint aDeviceId, TUint32 aLangId, TName& aString) const
       
  1090 	{
       
  1091 	LOG_FUNC
       
  1092 	LOGTEXT3(_L8("\taDeviceId = %d, aLangId = 0x%04x"), aDeviceId, aLangId);
       
  1093 
       
  1094 	CDeviceProxy* deviceProxy = DeviceProxyL(aDeviceId);
       
  1095 	deviceProxy->GetProductStringDescriptorL(aLangId, aString);
       
  1096 	LOGTEXT2(_L("\taString = \"%S\""), &aString);
       
  1097 	}
       
  1098 
       
  1099 void CFdf::GetOtgDeviceDescriptorL(TInt aDeviceId, TOtgDescriptor& aDescriptor) const
       
  1100 	{
       
  1101 	LOG_FUNC
       
  1102 	
       
  1103 	DeviceProxyL(aDeviceId)->GetOtgDescriptorL(aDescriptor);
       
  1104 	}
       
  1105 
       
  1106 void CFdf::GetSerialNumberStringDescriptorL(TUint aDeviceId, TUint32 aLangId, TName& aString) const
       
  1107 	{
       
  1108 	LOG_FUNC
       
  1109 	LOGTEXT3(_L8("\taDeviceId = %d, aLangId = 0x%04x"), aDeviceId, aLangId);
       
  1110 
       
  1111 	CDeviceProxy* deviceProxy = DeviceProxyL(aDeviceId);
       
  1112 	deviceProxy->GetSerialNumberStringDescriptorL(aLangId, aString);
       
  1113 	LOGTEXT2(_L("\taString = \"%S\""), &aString);
       
  1114 	}
       
  1115 
       
  1116 void CFdf::SearchForInterfaceFunctionDriversL(CDeviceProxy& aDevice, TBool& aAnySuccess, TInt& aCollectedErr)
       
  1117 	{
       
  1118 	RArray<TUint> interfacesNumberArray;	
       
  1119 	CleanupClosePushL(interfacesNumberArray);
       
  1120 
       
  1121 
       
  1122 	
       
  1123 	for ( TUint ii = 0 ; ii < iInterfaces.Count() ; ++ii )
       
  1124 		{
       
  1125 		// At this point we have NOT done any interface level searching yet,
       
  1126 		// and all interfaces should in the Unclaimed status,
       
  1127 		// just simply put them all into the interfacesNumberArray.
       
  1128 		TUint interfaceNumber = iInterfaces[ii]->iNumber; 
       
  1129 		AppendInterfaceNumberToArrayL(aDevice, interfacesNumberArray, interfaceNumber);
       
  1130 		}
       
  1131 
       
  1132 
       
  1133 	for ( TUint key = EVendorProductDeviceConfigurationvalueInterfacenumber ; key < EMaxInterfaceSearchKey ; ++key )
       
  1134 		{
       
  1135 		// Searching for proper FDCs based on different criteria.
       
  1136 		FindDriversForInterfacesUsingSpecificKeyL(aDevice,
       
  1137 												aCollectedErr,
       
  1138 												aAnySuccess,
       
  1139 												interfacesNumberArray,
       
  1140 												(TInterfaceSearchKeys) key);
       
  1141 							
       
  1142 		// If all the interfaces have been claimed by an FD then there is no point searching for other FDs							
       
  1143 		if (UnclaimedInterfaceCount() == 0)
       
  1144 			{
       
  1145 			break;
       
  1146 			}
       
  1147 		else
       
  1148 			{
       
  1149 			// Put all the unclaimed interface numbers into the array again.
       
  1150 			RebuildUnClaimedInterfacesArrayL(aDevice, interfacesNumberArray);
       
  1151 			}
       
  1152 		}
       
  1153 	CleanupStack::PopAndDestroy(&interfacesNumberArray);				
       
  1154 	}
       
  1155 void  CFdf::RebuildUnClaimedInterfacesArrayL(CDeviceProxy& aDevice, RArray<TUint>& aArray, TUint aOffset)
       
  1156 	{
       
  1157 	aArray.Reset();
       
  1158 	for ( TUint ii = aOffset ; ii < iInterfaces.Count() ; ++ii )
       
  1159 		{
       
  1160 			if (!iInterfaces[ii]->iClaimed)
       
  1161 				{
       
  1162 				TUint interfaceNumber = iInterfaces[ii]->iNumber; 
       
  1163 				AppendInterfaceNumberToArrayL(aDevice, aArray, interfaceNumber);
       
  1164 				}
       
  1165 		}
       
  1166 	}
       
  1167 
       
  1168 void CFdf::AppendInterfaceNumberToArrayL(CDeviceProxy& aDevice, RArray<TUint>& aArray, TUint aInterfaceNo) const
       
  1169 	{
       
  1170 	TInt err = aArray.Append(aInterfaceNo);
       
  1171 	if ( err )
       
  1172 		{
       
  1173 		aDevice.SetDriverLoadingEventData(EDriverLoadFailure, err);
       
  1174 		LEAVEL(err);
       
  1175 		}
       
  1176 	}
       
  1177 	
       
  1178 
       
  1179 
       
  1180 TBool CFdf::SearchForADeviceFunctionDriverL(CDeviceProxy& aDevice, TBool& aAnySuccess, TInt& aCollectedErr)
       
  1181 	{			
       
  1182 	
       
  1183 	RArray<TUint> interfaces;
       
  1184 	CleanupClosePushL(interfaces);
       
  1185 	
       
  1186 	for (TUint ii = 0; ii < iInterfaces.Count(); ++ii)
       
  1187 		{
       
  1188 		TUint interfaceNumber = iInterfaces[ii]->iNumber; 
       
  1189 		AppendInterfaceNumberToArrayL(aDevice, interfaces, interfaceNumber);
       
  1190 		}
       
  1191 	
       
  1192 	TBool foundFdc = EFalse;		
       
  1193 	for (TUint key = EVendorProductDevice; key < EMaxDeviceSearchKey; ++key)
       
  1194 		{		
       
  1195 		
       
  1196 		if (key == EVendorDevicesubclassDeviceprotocol && iDD.DeviceClass() != KVendorSpecificDeviceClassValue)
       
  1197 			continue;
       
  1198 		if (key == EVendorDevicesubclass && iDD.DeviceClass() != KVendorSpecificDeviceClassValue)
       
  1199 			continue;
       
  1200 		if (key == EDeviceclassDevicesubclassDeviceprotocol && iDD.DeviceClass() == KVendorSpecificDeviceClassValue)
       
  1201 			continue;
       
  1202 		if (key == EDeviceclassDevicesubclass && iDD.DeviceClass() == KVendorSpecificDeviceClassValue)
       
  1203 			continue;			
       
  1204 		
       
  1205 		TBuf8<KMaxSearchKeyLength> searchKeyString;
       
  1206 		FormatDeviceSearchKey(searchKeyString, (TDeviceSearchKeys)key);
       
  1207 
       
  1208 		// Find an FDC matching this search key.
       
  1209 		TSglQueIter<CFdcProxy> iter(iFunctionDrivers);
       
  1210 		iter.SetToFirst();
       
  1211 		CFdcProxy* fdc;
       
  1212 		while ( ( fdc = iter++ ) != NULL)
       
  1213 			{
       
  1214 			if (fdc->MarkedForDeletion())
       
  1215 				continue;
       
  1216 			LOGTEXT2(_L8("\tFDC's default_data field = \"%S\""), &fdc->DefaultDataField());
       
  1217 #ifdef _DEBUG
       
  1218 	// having these two together in the debug window is helpful for interactive debugging
       
  1219 	TBuf8<KMaxSearchKeyLength> fd_key;
       
  1220 	fd_key.Append(fdc->DefaultDataField().Ptr(), fdc->DefaultDataField().Length() > KMaxSearchKeyLength ? KMaxSearchKeyLength : fdc->DefaultDataField().Length());	
       
  1221 	TBuf8<KMaxSearchKeyLength> search_key;
       
  1222 	search_key.Append(searchKeyString.Ptr(), searchKeyString.Length() > KMaxSearchKeyLength ? KMaxSearchKeyLength : searchKeyString.Length());
       
  1223 	TInt version = fdc->Version();
       
  1224 #endif
       
  1225 			if (searchKeyString.CompareF(fdc->DefaultDataField()) == 0)
       
  1226 				{
       
  1227 				
       
  1228 				// If there is more than one matching FD then if all of them are in RAM we simply choose the first one we find.
       
  1229 				// (Similarly if they are all in ROM we choose the first one although this situation should not arise as a device
       
  1230 				// manufacturer should not put two matching FDs into ROM).
       
  1231 				// However if there are matching FDs in ROM and RAM then the one in ROM should be selected in preference to
       
  1232 				// any in RAM. Hence at this point if the matching FD we have found is in RAM then we need to scan the list
       
  1233 				// of FDs to see if there is also a matching one in ROM and if so we'll skip this iteration of the loop.
       
  1234 				//if (!fdc->RomBased() && FindMatchingRomBasedFD(searchKeyString))
       
  1235 				//	continue;
       
  1236 				if (FindMultipleFDs(searchKeyString, iter))
       
  1237 					{
       
  1238 					aDevice.SetMultipleDriversFlag();
       
  1239 					}
       
  1240 				
       
  1241 				foundFdc = ETrue;
       
  1242 				LOGTEXT2(_L8("\tfound matching FDC (0x%08x)"), fdc);
       
  1243 				TInt err = fdc->NewFunction(aDevice.DeviceId(), interfaces, iDD, iCD);
       
  1244 				LOGTEXT2(_L8("\tNewFunction returned %d"), err);
       
  1245 				// To correctly determine whether the driver load for the whole
       
  1246 				// configuration was a complete failure, a partial success or a
       
  1247 				// complete success, we need to collect any non-KErrNone error
       
  1248 				// from this, and whether any handovers worked at all.
       
  1249 				if ( err == KErrNone )
       
  1250 					{
       
  1251 					aAnySuccess = ETrue;
       
  1252 					}
       
  1253 				else
       
  1254 					{
       
  1255 					aCollectedErr = err;
       
  1256 					}
       
  1257 				break; 	// We found a matching FDC so no need to look for more.
       
  1258 				}
       
  1259 			}
       
  1260 		if (foundFdc)
       
  1261 			break;
       
  1262 		} // end of for
       
  1263 	CleanupStack::PopAndDestroy(&interfaces);
       
  1264 	return foundFdc;
       
  1265 		
       
  1266 	} // end of function
       
  1267 
       
  1268 
       
  1269 
       
  1270 
       
  1271 //
       
  1272 // Search the list of FDs looking for which matches with aSearchKey and is rom based and return true if found.
       
  1273 //
       
  1274 // added for Multiple FDs
       
  1275 TBool CFdf::FindMultipleFDs(const TDesC8& aSearchKey,TSglQueIter<CFdcProxy>& aFdcIter)
       
  1276 	{
       
  1277 	CFdcProxy* fdc;
       
  1278 	while ( ( fdc = aFdcIter++ ) != NULL)
       
  1279 		{
       
  1280 		if (!fdc->MarkedForDeletion() &&  (aSearchKey.CompareF(fdc->DefaultDataField()) == 0))
       
  1281 			return ETrue;
       
  1282 		}
       
  1283 		
       
  1284 	return EFalse;
       
  1285 	}
       
  1286 
       
  1287 //
       
  1288 // Format the string aSearchKey according to aSearchKeys to search for Device Functions drivers
       
  1289 //
       
  1290 void CFdf::FormatDeviceSearchKey(TDes8& aSearchKey, TDeviceSearchKeys aDeviceSearchKeys)
       
  1291 	{
       
  1292 	LOG_FUNC
       
  1293 	switch (aDeviceSearchKeys)
       
  1294 		{
       
  1295 		case EVendorProductDevice:
       
  1296 			{
       
  1297 			_LIT8(KTemplateV_P_D, "V0x%04xP0x%04xD0x%04x");
       
  1298 			aSearchKey.Format(KTemplateV_P_D(), iDD.VendorId(), iDD.ProductId(), iDD.DeviceBcd());
       
  1299 			break;
       
  1300 			}
       
  1301 		case EVendorProduct:
       
  1302 			{
       
  1303 			_LIT8(KTemplateV_P, "V0x%04xP0x%04x");
       
  1304 			aSearchKey.Format(KTemplateV_P(), iDD.VendorId(), iDD.ProductId());
       
  1305 			break;
       
  1306 			}
       
  1307 		case EVendorDevicesubclassDeviceprotocol:
       
  1308 			{
       
  1309 			_LIT8(KTemplateV_DSC_DP, "V0x%04xDSC0x%02xDP0x%02x");
       
  1310 			aSearchKey.Format(KTemplateV_DSC_DP(), iDD.VendorId(), iDD.DeviceSubClass(), iDD.DeviceProtocol());
       
  1311 			break;
       
  1312 			}
       
  1313 		case EVendorDevicesubclass:
       
  1314 			{
       
  1315 			_LIT8(KTemplateV_DSC, "V0x%04xDSC0x%02x");
       
  1316 			aSearchKey.Format(KTemplateV_DSC(), iDD.VendorId(), iDD.DeviceSubClass());
       
  1317 			break;
       
  1318 			}
       
  1319 		case EDeviceclassDevicesubclassDeviceprotocol:
       
  1320 			{
       
  1321 			_LIT8(KTemplateDC_DSC_DP, "DC0x%02xDSC0x%02xDP0x%02x");
       
  1322 			aSearchKey.Format(KTemplateDC_DSC_DP(), iDD.DeviceClass(), iDD.DeviceSubClass(), iDD.DeviceProtocol());
       
  1323 			break;
       
  1324 			}
       
  1325 		case EDeviceclassDevicesubclass:
       
  1326 			{
       
  1327 			_LIT8(KTemplateDC_DSC, "DC0x%02xDSC0x%02x");
       
  1328 			aSearchKey.Format(KTemplateDC_DSC(), iDD.DeviceClass(), iDD.DeviceSubClass());
       
  1329 			break;
       
  1330 			}
       
  1331 		default:
       
  1332 			{
       
  1333 			ASSERT_DEBUG(EFalse);
       
  1334 			}		
       
  1335 		}
       
  1336 		
       
  1337 	LOGTEXT2(_L8("\taSearchKey = \"%S\""), &aSearchKey);		
       
  1338 	}
       
  1339 	
       
  1340 	
       
  1341 	
       
  1342 	
       
  1343 
       
  1344 //
       
  1345 // Format the string aSearchKey according to aSearchKeys to search for Interface Functions drivers
       
  1346 //	
       
  1347 void CFdf::FormatInterfaceSearchKey(TDes8& aSearchKey, TInterfaceSearchKeys aSearchKeys, const TInterfaceInfo& aIfInfo)
       
  1348 	{
       
  1349 	LOG_FUNC
       
  1350 	switch (aSearchKeys)
       
  1351 		{
       
  1352 		case EVendorProductDeviceConfigurationvalueInterfacenumber:
       
  1353 			{
       
  1354 			_LIT8(KTemplateV_P_D_CV_IN, "V0x%04xP0x%04xD0x%04xCV0x%02xIN0x%02x");		
       
  1355 			aSearchKey.Format(KTemplateV_P_D_CV_IN(), iDD.VendorId(), iDD.ProductId(), iDD.DeviceBcd(), iCD.ConfigurationValue(), aIfInfo.iNumber);
       
  1356 			break;
       
  1357 			}
       
  1358 		case EVendorProductConfigurationValueInterfacenumber:
       
  1359 			{
       
  1360 			_LIT8(KTemplateV_P_CV_IN, "V0x%04xP0x%04xCV0x%02xIN0x%02x");
       
  1361 			aSearchKey.Format(KTemplateV_P_CV_IN(), iDD.VendorId(), iDD.ProductId(), iCD.ConfigurationValue(), aIfInfo.iNumber);
       
  1362 			break;
       
  1363 			}
       
  1364 		case EVendorInterfacesubclassInterfaceprotocol:
       
  1365 			{
       
  1366 			_LIT8(KTemplateV_ISC_IP, "V0x%04xISC0x%02xIP0x%02x");
       
  1367 			aSearchKey.Format(KTemplateV_ISC_IP(), iDD.VendorId(), aIfInfo.iSubclass, aIfInfo.iProtocol);
       
  1368 			break;
       
  1369 			}
       
  1370 		case EVendorInterfacesubclass:
       
  1371 			{
       
  1372 			_LIT8(KTemplateV_ISC, "V0x%04xISC0x%02x");
       
  1373 			aSearchKey.Format(KTemplateV_ISC(), iDD.VendorId(), aIfInfo.iSubclass);
       
  1374 			break;
       
  1375 			}
       
  1376 		case EInterfaceclassInterfacesubclassInterfaceprotocol:
       
  1377 			{
       
  1378 			_LIT8(KTemplateIC_ISC_IP, "IC0x%02xISC0x%02xIP0x%02x");
       
  1379 			aSearchKey.Format(KTemplateIC_ISC_IP(), aIfInfo.iClass, aIfInfo.iSubclass, aIfInfo.iProtocol);
       
  1380 			break;
       
  1381 			}
       
  1382 		case EInterfaceclassInterfacesubclass:
       
  1383 			{
       
  1384 			_LIT8(KTemplateIC_ISC, "IC0x%02xISC0x%02x");
       
  1385 			aSearchKey.Format(KTemplateIC_ISC(), aIfInfo.iClass, aIfInfo.iSubclass);
       
  1386 			break;
       
  1387 			}
       
  1388 		default:
       
  1389 			{
       
  1390 			ASSERT_DEBUG(EFalse);
       
  1391 			}
       
  1392 		}
       
  1393 	LOGTEXT2(_L8("\taSearchKey = \"%S\""), &aSearchKey);		
       
  1394 	}
       
  1395 
       
  1396 
       
  1397 TUint CFdf::UnclaimedInterfaceCount() const
       
  1398 	{
       
  1399 	LOG_FUNC	
       
  1400 	TUint unclaimedInterfaces = 0;
       
  1401 	for ( TUint ii = 0 ; ii < iInterfaces.Count() ; ++ii )
       
  1402 		{
       
  1403 		TInterfaceInfo* ifInfo = iInterfaces[ii];
       
  1404 		ASSERT_DEBUG(ifInfo);
       
  1405 		if ( !ifInfo->iClaimed )
       
  1406 			{
       
  1407 			LOGTEXT2(_L8("\tunclaimed interface: ifInfo->iNumber = %d"), ifInfo->iNumber);
       
  1408 			++unclaimedInterfaces;
       
  1409 			}
       
  1410 		}
       
  1411 	LOGTEXT2(_L("\tunclaimedInterfaces = \"%d\""), unclaimedInterfaces);			
       
  1412 	return unclaimedInterfaces;
       
  1413 	}
       
  1414 	
       
  1415 	
       
  1416 void CFdf::SetFailureStatus(TInt aUnclaimedInterfaces, TInt aInterfaceCount, TBool aAnySuccess, TBool aCollectedErr, CDeviceProxy& aDevice)
       
  1417 	{
       
  1418 	const TUint KMultipleDriverFound = aDevice.MultipleDriversFlag()?KMultipleDriversFound : 0;
       
  1419 	
       
  1420 	if (aUnclaimedInterfaces)
       
  1421 		{
       
  1422 		if(aUnclaimedInterfaces == aInterfaceCount)
       
  1423 			{
       
  1424 			// complete failure
       
  1425 			aDevice.SetDriverLoadingEventData((TDriverLoadStatus)(EDriverLoadFailure|KMultipleDriverFound), KErrUsbFunctionDriverNotFound);
       
  1426 			}
       
  1427 		else
       
  1428 			{// at that stage because we have unclaimed interfaces it means that
       
  1429 			// depending on anySuccess we have a failure or a partial success
       
  1430 			TDriverLoadStatus status = (aAnySuccess)? EDriverLoadPartialSuccess:EDriverLoadFailure;
       
  1431 			aDevice.SetDriverLoadingEventData((TDriverLoadStatus)(status|KMultipleDriverFound), KErrUsbFunctionDriverNotFound);
       
  1432 			}
       
  1433 		}
       
  1434 	else
       
  1435 		{
       
  1436 		if (aCollectedErr)
       
  1437 			{
       
  1438 			// There were no unclaimed interfaces, but an error was expressed.
       
  1439 			// This is either a partial success or a complete failure scenario.
       
  1440 			TDriverLoadStatus status = aAnySuccess ? EDriverLoadPartialSuccess : EDriverLoadFailure;
       
  1441 			aDevice.SetDriverLoadingEventData((TDriverLoadStatus)(status|KMultipleDriverFound), aCollectedErr);
       
  1442 			}
       
  1443 		else
       
  1444 			{
       
  1445 			// There were no unclaimed interfaces, and no error reported.
       
  1446 			aDevice.SetDriverLoadingEventData((TDriverLoadStatus)(EDriverLoadSuccess|KMultipleDriverFound));
       
  1447 			}
       
  1448 		}
       
  1449 	}	
       
  1450