usbmgmt/usbmgr/usbman/server/SRC/CUsbDevice.cpp
changeset 0 c9bc50fca66e
child 15 f92a4f87e424
equal deleted inserted replaced
-1:000000000000 0:c9bc50fca66e
       
     1 /*
       
     2 * Copyright (c) 1997-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 * Implements the main object of Usbman that manages all the USB Classes
       
    16 * and the USB Logical Device (via CUsbDeviceStateWatcher).
       
    17 *
       
    18 */
       
    19 
       
    20 /**
       
    21  @file
       
    22 */
       
    23 
       
    24 #include "CUsbDevice.h"
       
    25 #include "CUsbDeviceStateWatcher.h"
       
    26 #include <cusbclasscontrolleriterator.h>
       
    27 #include "MUsbDeviceNotify.h"
       
    28 #include "UsbSettings.h"
       
    29 #include "CUsbServer.h"
       
    30 #include <cusbclasscontrollerbase.h>
       
    31 #include <cusbclasscontrollerplugin.h>
       
    32 #include "UsbUtils.h"
       
    33 #include <cusbmanextensionplugin.h>
       
    34 
       
    35 #ifdef USE_DUMMY_CLASS_CONTROLLER
       
    36 #include "CUsbDummyClassController.h"
       
    37 #endif
       
    38 
       
    39 #include <bafl/sysutil.h>
       
    40 #include <usb/usblogger.h>
       
    41 #include <e32svr.h>
       
    42 #include <e32base.h>
       
    43 #include <e32std.h>
       
    44 #include <usbman.rsg>
       
    45 #include <f32file.h>
       
    46 #include <barsc.h>
       
    47 #include <barsread.h>
       
    48 #include <bautils.h>
       
    49 #include <e32property.h> //Publish & Subscribe header
       
    50 #include "CPersonality.h"
       
    51 
       
    52 _LIT(KUsbLDDName, "eusbc"); //Name used in call to User::LoadLogicalDevice
       
    53 _LIT(KUsbLDDFreeName, "Usbc"); //Name used in call to User::FreeLogicalDevice
       
    54 
       
    55 #ifdef __FLOG_ACTIVE
       
    56 _LIT8(KLogComponent, "USBSVR");
       
    57 #endif
       
    58 
       
    59 // Panic category only used in debug builds
       
    60 #ifdef _DEBUG
       
    61 _LIT(KUsbDevicePanicCategory, "UsbDevice");
       
    62 #endif
       
    63 
       
    64 /**
       
    65  * Panic codes for the USB Device Class
       
    66  */
       
    67 enum TUsbDevicePanic
       
    68 	{
       
    69 	/** Class called while in an illegal state */
       
    70 	EBadAsynchronousCall = 0,
       
    71 	EConfigurationError,
       
    72 	EResourceFileNotFound,
       
    73 	/** ConvertUidsL called with an array that is not empty */
       
    74 	EUidArrayNotEmpty,
       
    75 	};
       
    76 
       
    77 
       
    78 CUsbDevice* CUsbDevice::NewL(CUsbServer& aUsbServer)
       
    79 /**
       
    80  * Constructs a CUsbDevice object.
       
    81  *
       
    82  * @return	A new CUsbDevice object
       
    83  */
       
    84 	{
       
    85 	LOG_STATIC_FUNC_ENTRY
       
    86 
       
    87 	CUsbDevice* r = new (ELeave) CUsbDevice(aUsbServer);
       
    88 	CleanupStack::PushL(r);
       
    89 	r->ConstructL();
       
    90 	CleanupStack::Pop(r);
       
    91 	return r;
       
    92 	}
       
    93 
       
    94 
       
    95 CUsbDevice::~CUsbDevice()
       
    96 /**
       
    97  * Destructor.
       
    98  */
       
    99 	{
       
   100 	LOG_FUNC
       
   101 
       
   102 	// Cancel any outstanding asynchronous operation.
       
   103 	Cancel();
       
   104 	
       
   105 	delete iUsbClassControllerIterator;
       
   106 	iSupportedClasses.ResetAndDestroy();
       
   107 	iSupportedPersonalities.ResetAndDestroy();
       
   108 	iSupportedClassUids.Close();
       
   109 
       
   110 	iExtensionPlugins.ResetAndDestroy();
       
   111 
       
   112 	if(iEcom)
       
   113 		iEcom->Close();
       
   114 	REComSession::FinalClose();
       
   115 
       
   116 	// Free any memory allocated to the list of observers. Note that
       
   117 	// we don't want to call ResetAndDestroy, because we don't own
       
   118 	// the observers themselves.
       
   119 	iObservers.Reset();
       
   120 
       
   121 #ifndef __WINS__
       
   122 	LOGTEXT2(_L8("about to delete device state watcher @ %08x"), (TUint32) iDeviceStateWatcher);
       
   123 	delete iDeviceStateWatcher;
       
   124 	LOGTEXT(_L8("deleted device state watcher"));
       
   125 
       
   126 	iLdd.Close();
       
   127 
       
   128 	LOGTEXT(_L8("Freeing logical device"));
       
   129 	TInt err = User::FreeLogicalDevice(KUsbLDDFreeName);
       
   130 	//Putting the LOGTEXT2 inside the if statement prevents a compiler
       
   131 	//warning about err being unused in UREL builds.
       
   132 	if(err)
       
   133 		{
       
   134 		LOGTEXT2(_L8("     User::FreeLogicalDevice returned %d"),err);
       
   135 		}
       
   136 #endif	
       
   137 
       
   138 	delete iDefaultSerialNumber;
       
   139 	}
       
   140 
       
   141 
       
   142 CUsbDevice::CUsbDevice(CUsbServer& aUsbServer)
       
   143 	: CActive(EPriorityStandard)
       
   144 	, iDeviceState(EUsbDeviceStateUndefined)
       
   145 	, iServiceState(EUsbServiceIdle)
       
   146 	, iUsbServer(aUsbServer)
       
   147 	, iPersonalityCfged(EFalse)
       
   148 /**
       
   149  * Constructor.
       
   150  */
       
   151 	{
       
   152 	CActiveScheduler::Add(this);
       
   153 	}
       
   154 
       
   155 
       
   156 void CUsbDevice::ConstructL()
       
   157 /**
       
   158  * Performs 2nd phase construction of the USB device.
       
   159  */
       
   160 	{
       
   161 	LOG_FUNC
       
   162 	
       
   163 	iEcom = &(REComSession::OpenL());
       
   164 
       
   165 	iUsbClassControllerIterator = new(ELeave) CUsbClassControllerIterator(iSupportedClasses);
       
   166 
       
   167 #ifndef __WINS__
       
   168 	LOGTEXT(_L8("About to load LDD"));
       
   169 	TInt err = User::LoadLogicalDevice(KUsbLDDName);
       
   170 
       
   171 	if (err != KErrNone && err != KErrAlreadyExists)
       
   172 		{
       
   173 		LEAVEL(err);
       
   174 		}
       
   175 
       
   176 	LOGTEXT(_L8("About to open LDD"));
       
   177 	LEAVEIFERRORL(iLdd.Open(0));
       
   178 	LOGTEXT(_L8("LDD opened"));
       
   179 	
       
   180 	// hide bus from host while interfaces are being set up
       
   181 	iLdd.DeviceDisconnectFromHost();
       
   182 
       
   183 	// Does the USC support cable detection while powered off? If no, then 
       
   184 	// call PowerUpUdc when RUsb::Start finishes, as is obvious. If yes, we 
       
   185 	// delay calling PowerUpUdc until both the service state is 'started' and 
       
   186 	// the device state is not undefined. This is to save power in the UDC 
       
   187 	// when there's no point it being powered.
       
   188 	TUsbDeviceCaps devCapsBuf;
       
   189 	LEAVEIFERRORL(iLdd.DeviceCaps(devCapsBuf));
       
   190 	if ( devCapsBuf().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower )
       
   191 		{
       
   192 		LOGTEXT(_L8("\tUDC supports cable detect when unpowered"));
       
   193 		iUdcSupportsCableDetectWhenUnpowered = ETrue;
       
   194 		}
       
   195 	else
       
   196 		{
       
   197 		LOGTEXT(_L8("\tUDC does not support cable detect when unpowered"));
       
   198 		}
       
   199 
       
   200 	TUsbcDeviceState deviceState;
       
   201 	LEAVEIFERRORL(iLdd.DeviceStatus(deviceState));
       
   202 	SetDeviceState(deviceState);
       
   203 	LOGTEXT(_L8("Got device state"));
       
   204 
       
   205 	iDeviceStateWatcher = CUsbDeviceStateWatcher::NewL(*this, iLdd);
       
   206 	iDeviceStateWatcher->Start();
       
   207 
       
   208 	// Get hold of the default serial number in the driver
       
   209 	// This is so it can be put back in place when a device that sets a
       
   210 	// different serial number (through the P&S key) is stopped
       
   211 	iDefaultSerialNumber = HBufC16::NewL(KUsbStringDescStringMaxSize);
       
   212 	TPtr16 serNum = iDefaultSerialNumber->Des();
       
   213 	err = iLdd.GetSerialNumberStringDescriptor(serNum);
       
   214 	if (err == KErrNotFound)
       
   215 		{
       
   216 		delete iDefaultSerialNumber;
       
   217 		iDefaultSerialNumber = NULL;
       
   218 		LOGTEXT(_L8("No default serial number"));
       
   219 		}
       
   220 	else
       
   221 		{
       
   222 		LEAVEIFERRORL(err);
       
   223 #ifdef __FLOG_ACTIVE
       
   224 		TBuf8<KUsbStringDescStringMaxSize> narrowString;
       
   225 		narrowString.Copy(serNum);
       
   226 		LOGTEXT2(_L8("Got default serial number %S"), &narrowString);
       
   227 #endif //__FLOG_ACTIVE		
       
   228 		}
       
   229 
       
   230 	LOGTEXT(_L8("UsbDevice::ConstructL() finished"));
       
   231 #endif
       
   232 	
       
   233 #ifndef __OVER_DUMMYUSBDI__
       
   234 	InstantiateExtensionPluginsL();
       
   235 #endif
       
   236 	}
       
   237 
       
   238 void CUsbDevice::InstantiateExtensionPluginsL()
       
   239 	{
       
   240 	LOGTEXT(_L8(">>CUsbDevice::InstantiateExtensionPluginsL"));
       
   241 	const TUid KUidExtensionPluginInterface = TUid::Uid(KUsbmanExtensionPluginInterfaceUid);
       
   242 	RImplInfoPtrArray implementations;
       
   243 	const TEComResolverParams noResolverParams;
       
   244 	REComSession::ListImplementationsL(KUidExtensionPluginInterface, noResolverParams, KRomOnlyResolverUid, implementations);
       
   245 	CleanupResetAndDestroyPushL(implementations);
       
   246 	LOGTEXT2(_L8("Number of implementations of extension plugin interface: %d"), implementations.Count());
       
   247 
       
   248 	for (TInt i=0; i<implementations.Count(); i++)
       
   249 		{
       
   250 		CUsbmanExtensionPlugin* plugin = CUsbmanExtensionPlugin::NewL(implementations[i]->ImplementationUid(), *this);
       
   251 		CleanupStack::PushL(plugin);
       
   252 		iExtensionPlugins.AppendL(plugin); // transfer ownership to iExtensionPlugins
       
   253 		CleanupStack::Pop(plugin);
       
   254 		LOGTEXT2(_L8("Added extension plugin with UID 0x%08x"),
       
   255 			implementations[i]->ImplementationUid());
       
   256 		}
       
   257 
       
   258 	CleanupStack::PopAndDestroy(&implementations);
       
   259 
       
   260 	LOGTEXT(_L8("<<CUsbDevice::InstantiateExtensionPluginsL"));
       
   261 	}
       
   262 
       
   263 
       
   264 	
       
   265    	
       
   266 void CUsbDevice::EnumerateClassControllersL()
       
   267 /**
       
   268  * Loads all USB class controllers at startup.
       
   269  *
       
   270  */
       
   271 	{
       
   272 	LOG_FUNC
       
   273 	
       
   274 #ifdef USE_DUMMY_CLASS_CONTROLLER
       
   275 	//create a TLinearOrder to supply the comparison function, Compare(), to be used  
       
   276 	//to determine the order to add class controllers
       
   277 	TLinearOrder<CUsbClassControllerBase> order(CUsbClassControllerBase::Compare);
       
   278 	
       
   279 	// For GT171 automated tests, create three instances of the dummy class 
       
   280 	// controller, which will read their behaviour from an ini file. Do not 
       
   281 	// make any other class controllers.
       
   282 	for ( TUint ii = 0 ; ii < 3 ; ii++ )
       
   283 		{
       
   284 		AddClassControllerL(CUsbDummyClassController::NewL(*this, ii), order);	
       
   285 		}
       
   286 	    
       
   287 	LEAVEIFERRORL(iUsbClassControllerIterator->First());
       
   288 	    
       
   289 #else
       
   290 
       
   291 	// Add a class controller statically.
       
   292 	// The next line shows how to add a class controller, CUsbExampleClassController,
       
   293 	// statically
       
   294 
       
   295 	// AddClassControllerL(CUsbExampleClassController::NewL(*this),order);
       
   296 	
       
   297 	// Load class controller plug-ins
       
   298 
       
   299 	RImplInfoPtrArray implementations;
       
   300 
       
   301 	const TEComResolverParams noResolverParams;
       
   302 	REComSession::ListImplementationsL(KUidUsbPlugIns, noResolverParams, KRomOnlyResolverUid, implementations);
       
   303   	CleanupResetAndDestroyPushL(implementations);
       
   304   	
       
   305 	LOGTEXT2(_L8("Number of implementations to load  %d"), implementations.Count());
       
   306 	
       
   307 	for (TInt i=0; i<implementations.Count(); i++)
       
   308 		{
       
   309 		LOGTEXT2(_L8("Adding class controller with UID %x"),
       
   310 			implementations[i]->ImplementationUid());
       
   311 		const TUid uid = implementations[i]->ImplementationUid();
       
   312 		LEAVEIFERRORL(iSupportedClassUids.Append(uid));
       
   313 		}	
       
   314 			
       
   315 	CleanupStack::PopAndDestroy(&implementations);
       
   316 	
       
   317 #endif // USE_DUMMY_CLASS_CONTROLLER
       
   318 	}
       
   319 
       
   320 void CUsbDevice::AddClassControllerL(CUsbClassControllerBase* aClassController, 
       
   321 									TLinearOrder<CUsbClassControllerBase> aOrder)
       
   322 /**
       
   323  * Adds a USB class controller to the device. The controller will now be
       
   324  * managed by this device. Note that the class controller, aClassController, is now
       
   325  * owned by this function and can be destroyed by it.  Calling functions do not need to 
       
   326  * destroy the class controller. 
       
   327  *
       
   328  * @param	aClassController	Class to be managed
       
   329  * @param   aOrder              Specifies order CUsbClassControllerBase objects are to be
       
   330  *                              added
       
   331  */
       
   332 	{
       
   333 	LOG_FUNC
       
   334 	
       
   335 	
       
   336 	TInt rc = KErrNone;	
       
   337 	
       
   338 	if(isPersonalityCfged()) // do not take into account priorities
       
   339 		{
       
   340 		rc = iSupportedClasses.Append(aClassController);	
       
   341 		}
       
   342 	else
       
   343 		{
       
   344 		rc = iSupportedClasses.InsertInOrderAllowRepeats(
       
   345 		aClassController, aOrder);
       
   346 		} 
       
   347 		
       
   348 	if (rc != KErrNone) 
       
   349 		{
       
   350 		// Avoid memory leak by deleting class controller if the append fails.
       
   351 		delete aClassController;
       
   352 		LEAVEL(rc);
       
   353 		}
       
   354 	}
       
   355 
       
   356 void CUsbDevice::RegisterObserverL(MUsbDeviceNotify& aObserver)
       
   357 /**
       
   358  * Register an observer of the device.
       
   359  * Presently, the device supports watching state.
       
   360  *
       
   361  * @param	aObserver	New Observer of the device
       
   362  */
       
   363 	{
       
   364 	LOG_FUNC
       
   365 
       
   366 	LEAVEIFERRORL(iObservers.Append(&aObserver));
       
   367 	}
       
   368 
       
   369 
       
   370 void CUsbDevice::DeRegisterObserver(MUsbDeviceNotify& aObserver)
       
   371 /**
       
   372  * De-registers an existing device observer.
       
   373  *
       
   374  * @param	aObserver	The existing device observer to be de-registered
       
   375  */
       
   376 	{
       
   377 	LOG_FUNC
       
   378 
       
   379 	TInt index = iObservers.Find(&aObserver);
       
   380 
       
   381 	if (index >= 0)
       
   382 		iObservers.Remove(index);
       
   383 	}
       
   384 
       
   385 
       
   386 void CUsbDevice::StartL()
       
   387 /**
       
   388  * Start the USB Device and all its associated USB classes.
       
   389  * Reports errors and state changes via observer interface.
       
   390  */
       
   391 	{
       
   392 	LOG_FUNC
       
   393 
       
   394 	Cancel();
       
   395 	SetServiceState(EUsbServiceStarting);
       
   396 
       
   397 	TRAPD(err, SetDeviceDescriptorL());
       
   398 	if ( err != KErrNone )
       
   399 		{
       
   400 		SetServiceState(EUsbServiceIdle);
       
   401 		LEAVEL(err);		
       
   402 		}
       
   403 
       
   404 	iLastError = KErrNone;
       
   405 	StartCurrentClassController();
       
   406 	}
       
   407 
       
   408 void CUsbDevice::Stop()
       
   409 /**
       
   410  * Stop the USB device and all its associated USB classes.
       
   411  */
       
   412 	{
       
   413 	LOG_FUNC
       
   414 
       
   415 	Cancel();
       
   416 	SetServiceState(EUsbServiceStopping);
       
   417 	
       
   418 	iLastError = KErrNone;
       
   419 	StopCurrentClassController();
       
   420 	}
       
   421 
       
   422 void CUsbDevice::SetServiceState(TUsbServiceState aState)
       
   423 /**
       
   424  * Change the device's state and report the change to the observers.
       
   425  *
       
   426  * @param	aState	New state that the device is moving to
       
   427  */
       
   428 	{
       
   429 	LOGTEXT3(_L8("Calling: CUsbDevice::SetServiceState [iServiceState=%d,aState=%d]"),
       
   430 		iServiceState, aState);
       
   431 
       
   432 	if (iServiceState != aState)
       
   433 		{
       
   434 		// Change state straight away in case any of the clients check it
       
   435 		TUsbServiceState oldState = iServiceState;
       
   436 		iServiceState = aState;
       
   437 		TUint length = iObservers.Count();
       
   438 
       
   439 		for (TUint i = 0; i < length; i++)
       
   440 			{
       
   441 			iObservers[i]->UsbServiceStateChange(LastError(), oldState,
       
   442 				iServiceState);
       
   443 			}
       
   444 
       
   445 		if (iServiceState == EUsbServiceIdle)
       
   446 			iUsbServer.LaunchShutdownTimerIfNoSessions();
       
   447 		}
       
   448 	LOGTEXT(_L8("Exiting: CUsbDevice::SetServiceState"));
       
   449 	}
       
   450 
       
   451 void CUsbDevice::SetDeviceState(TUsbcDeviceState aState)
       
   452 /**
       
   453  * The CUsbDevice::SetDeviceState method
       
   454  *
       
   455  * Change the device's state and report the change to the observers
       
   456  *
       
   457  * @internalComponent
       
   458  * @param	aState	New state that the device is moving to
       
   459  */
       
   460 	{
       
   461 	LOG_FUNC
       
   462 	LOGTEXT3(_L8("\taState = %d, iDeviceState = %d"), aState, iDeviceState);
       
   463 
       
   464 	TUsbDeviceState state;
       
   465 	switch (aState)
       
   466 		{
       
   467 	case EUsbcDeviceStateUndefined:
       
   468 		state = EUsbDeviceStateUndefined;
       
   469 		break;
       
   470 	case EUsbcDeviceStateAttached:
       
   471 		state = EUsbDeviceStateAttached;
       
   472 		break;
       
   473 	case EUsbcDeviceStatePowered:
       
   474 		state = EUsbDeviceStatePowered;
       
   475 		break;
       
   476 	case EUsbcDeviceStateDefault:
       
   477 		state = EUsbDeviceStateDefault;
       
   478 		break;
       
   479 	case EUsbcDeviceStateAddress:
       
   480 		state = EUsbDeviceStateAddress;
       
   481 		break;
       
   482 	case EUsbcDeviceStateConfigured:
       
   483 		state = EUsbDeviceStateConfigured;
       
   484 		break;
       
   485 	case EUsbcDeviceStateSuspended:
       
   486 		state = EUsbDeviceStateSuspended;
       
   487 		break;
       
   488 	default:
       
   489 		return;
       
   490 		}
       
   491 
       
   492 	if (iDeviceState != state)
       
   493 		{
       
   494 #ifndef __WINS__
       
   495 		if (iDeviceState == EUsbDeviceStateUndefined &&
       
   496 			iUdcSupportsCableDetectWhenUnpowered &&
       
   497 			iServiceState == EUsbServiceStarted)
       
   498 			{
       
   499 			// We just changed state away from undefined. Hence the cable must
       
   500 			// now be attached (if it wasn't before). If the UDC supports
       
   501 			// cable detection when unpowered, NOW is the right time to power
       
   502 			// it up (so long as usbman is fully started).
       
   503 			(void)PowerUpAndConnect(); // We don't care about any errors here.
       
   504 			}
       
   505 #endif // __WINS__
       
   506 		// Change state straight away in case any of the clients check it
       
   507 		TUsbDeviceState oldState = iDeviceState;
       
   508 		iDeviceState = state;
       
   509 		TUint length = iObservers.Count();
       
   510 
       
   511 		for (TUint i = 0; i < length; i++)
       
   512 			{
       
   513 			iObservers[i]->UsbDeviceStateChange(LastError(), oldState, iDeviceState);
       
   514 			}
       
   515 		}
       
   516 	}
       
   517 
       
   518 /**
       
   519  * Callback called by CDeviceHandler when the USB bus has sucessfully
       
   520  * completed a ReEnumeration (restarted all services).
       
   521  */
       
   522 void CUsbDevice::BusEnumerationCompleted()
       
   523 	{
       
   524 	LOG_FUNC
       
   525 
       
   526 	// Has the start been cancelled?
       
   527 	if (iServiceState == EUsbServiceStarting)
       
   528 		{
       
   529 		SetServiceState(EUsbServiceStarted);
       
   530 		}
       
   531 	else
       
   532 		{
       
   533 		LOGTEXT(_L8("    Start has been cancelled!"));
       
   534 		}
       
   535 	}
       
   536 
       
   537 void CUsbDevice::BusEnumerationFailed(TInt aError)
       
   538 /**
       
   539  * Callback called by CDeviceHandler when the USB bus has
       
   540  * completed an ReEnumeration (Restarted all services) with errors
       
   541  *
       
   542  * @param	aError	Error that has occurred during Re-enumeration
       
   543  */
       
   544 	{
       
   545 	LOGTEXT2(_L8("CUsbDevice::BusEnumerationFailed [aError=%d]"), aError);
       
   546 	iLastError = aError;
       
   547 
       
   548 	if (iServiceState == EUsbServiceStarting)
       
   549 		{
       
   550 		SetServiceState(EUsbServiceStopping);
       
   551 		StopCurrentClassController();
       
   552 		}
       
   553 	else
       
   554 		{
       
   555 		LOGTEXT(_L8("    Start has been cancelled!"));
       
   556 		}
       
   557 	}
       
   558 
       
   559 
       
   560 void CUsbDevice::StartCurrentClassController()
       
   561 /**
       
   562  * Called numerous times to start all the USB classes.
       
   563  */
       
   564 	{
       
   565 	LOG_FUNC
       
   566 
       
   567 	iUsbClassControllerIterator->Current()->Start(iStatus);
       
   568 	SetActive();
       
   569 	}
       
   570 
       
   571 void CUsbDevice::StopCurrentClassController()
       
   572 /**
       
   573  * Called numerous times to stop all the USB classes.
       
   574  */
       
   575 	{
       
   576 	LOG_FUNC
       
   577 
       
   578 	iUsbClassControllerIterator->Current()->Stop(iStatus);
       
   579 	SetActive();
       
   580 	}
       
   581 
       
   582 /**
       
   583 Utility function to power up the UDC and connect the
       
   584 device to the host.
       
   585 */
       
   586 TInt CUsbDevice::PowerUpAndConnect()
       
   587 	{
       
   588 	LOG_FUNC
       
   589 	LOGTEXT(_L8("\tPowering up UDC..."));
       
   590 	TInt res = iLdd.PowerUpUdc();
       
   591 	LOGTEXT2(_L8("\tPowerUpUdc res = %d"), res);
       
   592 	res = iLdd.DeviceConnectToHost();
       
   593 	LOGTEXT2(_L8("\tDeviceConnectToHost res = %d"), res);
       
   594 	return res;
       
   595 	}
       
   596 
       
   597 void CUsbDevice::RunL()
       
   598 /**
       
   599  * Called when starting or stopping a USB class has completed, successfully or
       
   600  * otherwise. Continues with the process of starting or stopping until all
       
   601  * classes have been completed.
       
   602  */
       
   603 	{
       
   604 	LOGTEXT2(_L8(">>CUsbDevice::RunL [iStatus=%d]"), iStatus.Int());
       
   605 
       
   606 	LEAVEIFERRORL(iStatus.Int());
       
   607 
       
   608 	switch (iServiceState)
       
   609 		{
       
   610 	case EUsbServiceStarting:
       
   611 		if (iUsbClassControllerIterator->Next() == KErrNotFound)
       
   612 			{
       
   613 #ifndef __WINS__
       
   614 			if (!iUdcSupportsCableDetectWhenUnpowered || iDeviceState != EUsbDeviceStateUndefined)
       
   615 				{
       
   616 				// We've finished starting the classes. We can just power up the UDC
       
   617 				// now: there's no need to re-enumerate, because we soft disconnected
       
   618 				// earlier. This will also do a soft connect.
       
   619 				LOGTEXT(_L8("Finished starting classes: powering up UDC"));
       
   620 
       
   621 				// It isn't an error if this call fails. This will happen, for example,
       
   622 				// in the case where there are no USB classes defined.
       
   623 				(void)PowerUpAndConnect();
       
   624 				}
       
   625 #endif
       
   626 			// If we're not running on target, we can just go to "started".
       
   627 			SetServiceState(EUsbServiceStarted);
       
   628 			}
       
   629 		else
       
   630 			{
       
   631 			StartCurrentClassController();
       
   632 			}
       
   633 		break;
       
   634 
       
   635 	case EUsbServiceStopping:
       
   636 		if (iUsbClassControllerIterator->Previous() == KErrNotFound)
       
   637 			{
       
   638 			// if stopping classes, hide the USB interface from the host
       
   639 #ifndef __WINS__
       
   640 			iLdd.DeviceDisconnectFromHost();
       
   641 
       
   642 			// Restore the default serial number 
       
   643 			if (iDefaultSerialNumber)
       
   644 				{
       
   645 				TInt res = iLdd.SetSerialNumberStringDescriptor(*iDefaultSerialNumber);
       
   646 				LOGTEXT2(_L8("Restore default serial number res = %d"), res);
       
   647 				}
       
   648 			else
       
   649 				{
       
   650 				TInt res = iLdd.RemoveSerialNumberStringDescriptor();
       
   651 				LOGTEXT2(_L8("Remove serial number res = %d"), res);
       
   652 				}
       
   653 				
       
   654 #endif			
       
   655 			SetServiceState(EUsbServiceIdle);
       
   656 			}
       
   657 		else
       
   658 			{
       
   659 			StopCurrentClassController();
       
   660 			}
       
   661 		break;
       
   662 
       
   663 	default:
       
   664 		__ASSERT_DEBUG( EFalse, _USB_PANIC(KUsbDevicePanicCategory, EBadAsynchronousCall) );
       
   665 		break;
       
   666 		}
       
   667 	LOGTEXT(_L8("<<CUsbDevice::RunL"));
       
   668 	}
       
   669 
       
   670 void CUsbDevice::DoCancel()
       
   671 /**
       
   672  * Standard active object cancellation function. If we're starting or stopping
       
   673  * a USB class, cancels it. If we're not, then we shouldn't be active and hence
       
   674  * this function being called is a programming error.
       
   675  */
       
   676 	{
       
   677 	LOG_FUNC
       
   678 
       
   679 	switch (iServiceState)
       
   680 		{
       
   681 	case EUsbServiceStarting:
       
   682 	case EUsbServiceStopping:
       
   683 		iUsbClassControllerIterator->Current()->Cancel();
       
   684 		break;
       
   685 
       
   686 	default:
       
   687 		__ASSERT_DEBUG( EFalse, _USB_PANIC(KUsbDevicePanicCategory, EBadAsynchronousCall) );
       
   688 		break;
       
   689 		}
       
   690 	}
       
   691 
       
   692 TInt CUsbDevice::RunError(TInt aError)
       
   693 /**
       
   694  * Standard active object RunError function. Handles errors which occur when
       
   695  * starting and stopping the USB class objects.
       
   696  *
       
   697  * @param aError The error which occurred
       
   698  * @return Always KErrNone, to avoid an active scheduler panic
       
   699  */
       
   700 	{
       
   701 	LOGTEXT2(_L8("CUsbDevice::RunError [aError=%d]"), aError);
       
   702 
       
   703 	iLastError = aError;
       
   704 
       
   705 	switch (iServiceState)
       
   706 		{
       
   707 	case EUsbServiceStarting:
       
   708 	case EUsbServiceStarted:
       
   709 		// An error has happened while we're either started or starting, so
       
   710 		// we have to stop all the classes which were successfully started.
       
   711 		if ((iUsbClassControllerIterator->Current()->State() ==
       
   712 				EUsbServiceIdle) &&
       
   713 			(iUsbClassControllerIterator->Previous() == KErrNotFound))
       
   714 			{
       
   715 			SetServiceState(EUsbServiceIdle);
       
   716 			}
       
   717 		else
       
   718 			{
       
   719 			SetServiceState(EUsbServiceStopping);
       
   720 			StopCurrentClassController();
       
   721 			}
       
   722 		break;
       
   723 
       
   724 	case EUsbServiceStopping:
       
   725 		// Argh, we've got problems. Let's stop as many classes as we can.
       
   726 		if (iUsbClassControllerIterator->Previous() == KErrNotFound)
       
   727 			SetServiceState(EUsbServiceIdle);
       
   728 		else
       
   729 			StopCurrentClassController();
       
   730 		break;
       
   731 
       
   732 	default:
       
   733 		__ASSERT_DEBUG( EFalse, _USB_PANIC(KUsbDevicePanicCategory, EBadAsynchronousCall) );
       
   734 		break;
       
   735 		}
       
   736 
       
   737 	return KErrNone;
       
   738 	}
       
   739 
       
   740 CUsbClassControllerIterator* CUsbDevice::UccnGetClassControllerIteratorL()
       
   741 /**
       
   742  * Function used by USB classes to get an iterator over the set of classes
       
   743  * owned by this device. Note that the caller takes ownership of the iterator
       
   744  * which this function returns.
       
   745  *
       
   746  * @return A new iterator
       
   747  */
       
   748 	{
       
   749 	LOG_FUNC
       
   750 
       
   751 	return new (ELeave) CUsbClassControllerIterator(iSupportedClasses);
       
   752 	}
       
   753 
       
   754 void CUsbDevice::UccnError(TInt aError)
       
   755 /**
       
   756  * Function called by USB classes to notify the device of a fatal error. In
       
   757  * this situation, we should just stop all the classes we can.
       
   758  *
       
   759  * @param aError The error that's occurred
       
   760  */
       
   761 	{
       
   762 	LOG_FUNC
       
   763 
       
   764 	RunError(aError);
       
   765 	}
       
   766 
       
   767 
       
   768 #ifdef __FLOG_ACTIVE
       
   769 void CUsbDevice::PrintDescriptor(CUsbDevice::TUsbDeviceDescriptor& aDeviceDescriptor)
       
   770 	{
       
   771 	LOGTEXT2(_L8("\tiLength is %d"), aDeviceDescriptor.iLength);
       
   772 	LOGTEXT2(_L8("\tiDescriptorType is %d"), aDeviceDescriptor.iDescriptorType);
       
   773 	LOGTEXT2(_L8("\tBcdUsb is: 0x%04x"), aDeviceDescriptor.iBcdUsb);
       
   774 	LOGTEXT2(_L8("\tDeviceClass is: 0x%02x"), aDeviceDescriptor.iDeviceClass);
       
   775 	LOGTEXT2(_L8("\tDeviceSubClass is: 0x%02x"), aDeviceDescriptor.iDeviceSubClass);
       
   776 	LOGTEXT2(_L8("\tDeviceProtocol is: 0x%02x"), aDeviceDescriptor.iDeviceProtocol);
       
   777 	LOGTEXT2(_L8("\tiMaxPacketSize is: 0x%02x"), aDeviceDescriptor.iMaxPacketSize);
       
   778 	
       
   779 	LOGTEXT2(_L8("\tVendorId is: 0x%04x"), aDeviceDescriptor.iIdVendor);
       
   780 	LOGTEXT2(_L8("\tProductId is: 0x%04x"), aDeviceDescriptor.iIdProduct);
       
   781 	LOGTEXT2(_L8("\tBcdDevice is: 0x%04x"), aDeviceDescriptor.iBcdDevice);
       
   782 
       
   783 	LOGTEXT2(_L8("\tiManufacturer is: 0x%04x"), aDeviceDescriptor.iManufacturer);
       
   784 	LOGTEXT2(_L8("\tiSerialNumber is: 0x%04x"), aDeviceDescriptor.iSerialNumber);
       
   785 	LOGTEXT2(_L8("\tiNumConfigurations is: 0x%04x"), aDeviceDescriptor.iNumConfigurations);
       
   786 	}
       
   787 #endif
       
   788 //
       
   789 void CUsbDevice::SetDeviceDescriptorL()
       
   790 /**
       
   791  * Modifies the USB device descriptor.
       
   792  */
       
   793 	{
       
   794 	LOG_FUNC
       
   795 
       
   796 #ifndef __WINS__
       
   797 
       
   798 	TInt desSize = 0;
       
   799 	iLdd.GetDeviceDescriptorSize(desSize);
       
   800 	LOGTEXT2(_L8("UDeviceDescriptorSize = %d"), desSize);
       
   801 	HBufC8* deviceBuf = HBufC8::NewLC(desSize);
       
   802 	TPtr8   devicePtr = deviceBuf->Des();
       
   803 	devicePtr.SetLength(0);
       
   804 
       
   805 	TInt ret = iLdd.GetDeviceDescriptor(devicePtr);
       
   806 
       
   807 	if (ret != KErrNone)
       
   808 		{
       
   809 		LOGTEXT2(_L8("Unable to fetch device descriptor. Error: %d"), ret);
       
   810 		LEAVEL(ret);
       
   811 		}
       
   812 
       
   813 	TUsbDeviceDescriptor* deviceDescriptor = reinterpret_cast<TUsbDeviceDescriptor*>(
       
   814 		const_cast<TUint8*>(devicePtr.Ptr()));
       
   815 
       
   816 
       
   817 #else
       
   818 
       
   819 	// Create an empty descriptor to allow the settings
       
   820 	// to be read in from the resource file
       
   821 	TUsbDeviceDescriptor descriptor;
       
   822 	TUsbDeviceDescriptor* deviceDescriptor = &descriptor;
       
   823 	
       
   824 #endif // __WINS__
       
   825 
       
   826 	if (iPersonalityCfged)
       
   827 		{
       
   828 		SetUsbDeviceSettingsFromPersonalityL(*deviceDescriptor);		
       
   829 		}
       
   830 	else
       
   831 		{
       
   832 	SetUsbDeviceSettingsL(*deviceDescriptor);
       
   833 		}
       
   834 	
       
   835 #ifndef __WINS__
       
   836 	ret = iLdd.SetDeviceDescriptor(devicePtr);
       
   837 
       
   838 	if (ret != KErrNone)
       
   839 		{
       
   840 		LOGTEXT2(_L8("Unable to set device descriptor. Error: %d"), ret);
       
   841 		LEAVEL(ret);
       
   842 		}
       
   843 
       
   844 	CleanupStack::PopAndDestroy(deviceBuf);
       
   845 
       
   846 #endif // __WINS__
       
   847 	}
       
   848 
       
   849 void CUsbDevice::SetUsbDeviceSettingsDefaultsL(CUsbDevice::TUsbDeviceDescriptor& aDeviceDescriptor)
       
   850 /**
       
   851  * Set the device settings defaults, as per the non-resource
       
   852  * version of the USB manager
       
   853  *
       
   854  * @param aDeviceDescriptor The device descriptor for the USB device
       
   855  */
       
   856 	{
       
   857 	aDeviceDescriptor.iDeviceClass		= KUsbDefaultDeviceClass;
       
   858 	aDeviceDescriptor.iDeviceSubClass	= KUsbDefaultDeviceSubClass;
       
   859 	aDeviceDescriptor.iDeviceProtocol	= KUsbDefaultDeviceProtocol;
       
   860 	aDeviceDescriptor.iIdVendor			= KUsbDefaultVendorId;
       
   861 	aDeviceDescriptor.iIdProduct		= KUsbDefaultProductId;
       
   862 	}
       
   863 
       
   864 void CUsbDevice::SetUsbDeviceSettingsL(CUsbDevice::TUsbDeviceDescriptor& aDeviceDescriptor)
       
   865 /**
       
   866  * Configure the USB device, reading in the settings from a
       
   867  * resource file where possible.
       
   868  *
       
   869  * @param aDeviceDescriptor The device descriptor for the USB device
       
   870  */
       
   871 	{
       
   872 	LOG_FUNC
       
   873 
       
   874 	// First, use the default values
       
   875 	LOGTEXT(_L8("Setting default values for the configuration"));
       
   876 	SetUsbDeviceSettingsDefaultsL(aDeviceDescriptor);
       
   877 
       
   878 	// Now try to get the configuration from the resource file
       
   879 	RFs fs;
       
   880 	LEAVEIFERRORL(fs.Connect());
       
   881 	CleanupClosePushL(fs);
       
   882 
       
   883 	RResourceFile resource;
       
   884 	TRAPD(err, resource.OpenL(fs, KUsbManagerResource));
       
   885 	LOGTEXT2(_L8("Opened resource file with error %d"), err);
       
   886 
       
   887 	if (err != KErrNone)
       
   888 		{
       
   889 		LOGTEXT(_L8("Unable to open resource file: using default settings"));
       
   890 		CleanupStack::PopAndDestroy(&fs);
       
   891 		return;
       
   892 		}
       
   893 
       
   894 	CleanupClosePushL(resource);
       
   895 
       
   896 	resource.ConfirmSignatureL(KUsbManagerResourceVersion);
       
   897 
       
   898 	HBufC8* id = resource.AllocReadLC(USB_CONFIG);
       
   899 
       
   900 	// The format of the USB resource structure is:
       
   901 	//
       
   902 	//	STRUCT usb_configuration
       
   903 	//		{
       
   904 	//		WORD	vendorId		= 0x0e22;
       
   905 	//		WORD	productId		= 0x000b;
       
   906 	//		WORD	bcdDevice		= 0x0000;
       
   907 	//		LTEXT	manufacturer	= "Symbian Ltd.";
       
   908 	//		LTEXT	product			= "Symbian OS";
       
   909 	//		}
       
   910 	//
       
   911 	// Note that the resource must be read in this order!
       
   912 	
       
   913 	TResourceReader reader;
       
   914 	reader.SetBuffer(id);
       
   915 
       
   916 	aDeviceDescriptor.iIdVendor = static_cast<TUint16>(reader.ReadUint16());
       
   917 	aDeviceDescriptor.iIdProduct = static_cast<TUint16>(reader.ReadUint16());
       
   918 	aDeviceDescriptor.iBcdDevice = static_cast<TUint16>(reader.ReadUint16());
       
   919 
       
   920 	// Try to read device and manufacturer name from new SysUtil API
       
   921 	TPtrC16 sysUtilModelName;
       
   922 	TPtrC16 sysUtilManuName;
       
   923 	
       
   924 	// This method returns ownership.
       
   925 	CDeviceTypeInformation* deviceInfo = SysUtil::GetDeviceTypeInfoL();
       
   926 	CleanupStack::PushL(deviceInfo);
       
   927 	TInt gotSysUtilModelName = deviceInfo->GetModelName(sysUtilModelName);
       
   928 	TInt gotSysUtilManuName = deviceInfo->GetManufacturerName(sysUtilManuName);
       
   929 	
       
   930 	TPtrC manufacturerString = reader.ReadTPtrC();
       
   931 	TPtrC productString = reader.ReadTPtrC();
       
   932 	
       
   933 	// If we succesfully read the manufacturer or device name from SysUtil API
       
   934 	// then set these results, otherwise use the values defined in resource file
       
   935 #ifndef __WINS__
       
   936 	if (gotSysUtilManuName == KErrNone)
       
   937 		{
       
   938 		LEAVEIFERRORL(iLdd.SetManufacturerStringDescriptor(sysUtilManuName));
       
   939 		}
       
   940 	else
       
   941 		{
       
   942 		LEAVEIFERRORL(iLdd.SetManufacturerStringDescriptor(manufacturerString));
       
   943 		}
       
   944 
       
   945 	if (gotSysUtilModelName == KErrNone)
       
   946 		{
       
   947 		LEAVEIFERRORL(iLdd.SetProductStringDescriptor(sysUtilModelName));
       
   948 		}
       
   949 	else
       
   950 		{
       
   951 		LEAVEIFERRORL(iLdd.SetProductStringDescriptor(productString));
       
   952 		}
       
   953 #endif // __WINS__
       
   954 
       
   955 #ifdef __FLOG_ACTIVE
       
   956 	PrintDescriptor(aDeviceDescriptor);	
       
   957 	TBuf8<KUsbStringDescStringMaxSize> narrowString;
       
   958 	narrowString.Copy(manufacturerString);
       
   959 	LOGTEXT2(_L8("Manufacturer is: '%S'"), &narrowString);
       
   960 	narrowString.Copy(productString);
       
   961 	LOGTEXT2(_L8("Product is: '%S'"), &narrowString);
       
   962 #endif // __FLOG_ACTIVE
       
   963 
       
   964 #ifndef __WINS__	
       
   965 	//Read the published serial number. The key is the UID KUidUsbmanServer = 0x101FE1DB
       
   966 	TBuf16<KUsbStringDescStringMaxSize> serNum;
       
   967 	TInt r = RProperty::Get(KUidSystemCategory,0x101FE1DB,serNum);
       
   968 	if(r==KErrNone)
       
   969 		{
       
   970 #ifdef __FLOG_ACTIVE
       
   971 		TBuf8<KUsbStringDescStringMaxSize> narrowString;
       
   972 		narrowString.Copy(serNum);
       
   973 		LOGTEXT2(_L8("Setting published SerialNumber: %S"), &narrowString);
       
   974 #endif // __FLOG_ACTIVE
       
   975 		//USB spec doesn't give any constraints on what constitutes a valid serial number.
       
   976 		//As long as it is a string descriptor it is valid.
       
   977 		LEAVEIFERRORL(iLdd.SetSerialNumberStringDescriptor(serNum));	
       
   978 		}
       
   979 #ifdef __FLOG_ACTIVE
       
   980 	else
       
   981 		{
       
   982 		LOGTEXT(_L8("SerialNumber has not been published"));	
       
   983 		}
       
   984 #endif // __FLOG_ACTIVE
       
   985 #endif // __WINS__
       
   986 
       
   987 
       
   988 	CleanupStack::PopAndDestroy(4, &fs); //  deviceInfo, id, resource, fs
       
   989 	}
       
   990 
       
   991 void CUsbDevice::SetUsbDeviceSettingsFromPersonalityL(CUsbDevice::TUsbDeviceDescriptor& aDeviceDescriptor)
       
   992 /**
       
   993  * Configure the USB device from the current personality.
       
   994  *
       
   995  * @param aDeviceDescriptor The device descriptor for the USB device
       
   996  */
       
   997 	{
       
   998 	LOG_FUNC
       
   999 
       
  1000 	// First, use the default values
       
  1001 	LOGTEXT(_L8("Setting default values for the configuration"));
       
  1002 	SetUsbDeviceSettingsDefaultsL(aDeviceDescriptor);
       
  1003 
       
  1004 	// Now try to get the configuration from the current personality
       
  1005 	const CUsbDevice::TUsbDeviceDescriptor& deviceDes = iCurrentPersonality->DeviceDescriptor();
       
  1006 	aDeviceDescriptor.iDeviceClass			= deviceDes.iDeviceClass;
       
  1007 	aDeviceDescriptor.iDeviceSubClass		= deviceDes.iDeviceSubClass;
       
  1008 	aDeviceDescriptor.iDeviceProtocol		= deviceDes.iDeviceProtocol;
       
  1009 	aDeviceDescriptor.iIdVendor				= deviceDes.iIdVendor;
       
  1010 	aDeviceDescriptor.iIdProduct			= deviceDes.iIdProduct;
       
  1011 	aDeviceDescriptor.iBcdDevice			= deviceDes.iBcdDevice;
       
  1012 	aDeviceDescriptor.iSerialNumber			= deviceDes.iSerialNumber;
       
  1013 	aDeviceDescriptor.iNumConfigurations	= deviceDes.iNumConfigurations;
       
  1014 
       
  1015 #ifndef __WINS__
       
  1016 	LEAVEIFERRORL(iLdd.SetManufacturerStringDescriptor(*(iCurrentPersonality->Manufacturer())));
       
  1017 	LEAVEIFERRORL(iLdd.SetProductStringDescriptor(*(iCurrentPersonality->Product())));
       
  1018 
       
  1019 	//Read the published serial number. The key is the UID KUidUsbmanServer = 0x101FE1DB
       
  1020 	TBuf16<KUsbStringDescStringMaxSize> serNum;
       
  1021 	TInt r = RProperty::Get(KUidSystemCategory,0x101FE1DB,serNum);
       
  1022 	if(r==KErrNone)
       
  1023 		{
       
  1024 #ifdef __FLOG_ACTIVE
       
  1025 		TBuf8<KUsbStringDescStringMaxSize> narrowString;
       
  1026 		narrowString.Copy(serNum);
       
  1027 		LOGTEXT2(_L8("Setting published SerialNumber: %S"), &narrowString);
       
  1028 #endif // __FLOG_ACTIVE
       
  1029 		//USB spec doesn't give any constraints on what constitutes a valid serial number.
       
  1030 		//As long as it is a string descriptor it is valid.
       
  1031 		LEAVEIFERRORL(iLdd.SetSerialNumberStringDescriptor(serNum));	
       
  1032 		}
       
  1033 #ifdef __FLOG_ACTIVE
       
  1034 	else
       
  1035 		{
       
  1036 		LOGTEXT(_L8("SerialNumber has not been published"));	
       
  1037 		}
       
  1038 #endif // __FLOG_ACTIVE
       
  1039 #endif // __WINS__
       
  1040 
       
  1041 
       
  1042 #ifdef __FLOG_ACTIVE
       
  1043 	PrintDescriptor(aDeviceDescriptor);		
       
  1044 
       
  1045 #ifndef __WINS__
       
  1046 	TBuf16<KUsbStringDescStringMaxSize> wideString;
       
  1047 	TBuf8<KUsbStringDescStringMaxSize> narrowString;
       
  1048 
       
  1049 	LEAVEIFERRORL(iLdd.GetConfigurationStringDescriptor(wideString));
       
  1050 	narrowString.Copy(wideString);
       
  1051 	LOGTEXT2(_L8("Configuration is: '%S'"), &narrowString);
       
  1052 #endif // __WINS__
       
  1053 
       
  1054 #endif // __FLOG_ACTIVE
       
  1055 	}
       
  1056 	
       
  1057 void CUsbDevice::TryStartL(TInt aPersonalityId)
       
  1058 /**
       
  1059  * Start all USB classes associated with the personality identified
       
  1060  * by aPersonalityId. Reports errors and state changes via observer 
       
  1061  * interface.
       
  1062  *
       
  1063  * @param aPersonalityId a personality id
       
  1064  */
       
  1065 	{
       
  1066 	LOG_FUNC
       
  1067 	SetCurrentPersonalityL(aPersonalityId);
       
  1068 	
       
  1069 	SelectClassControllersL();
       
  1070 	SetServiceState(EUsbServiceStarting);
       
  1071 
       
  1072 	TRAPD(err, SetDeviceDescriptorL());
       
  1073 	if ( err != KErrNone )
       
  1074 		{
       
  1075 		SetServiceState(EUsbServiceIdle);
       
  1076 		LEAVEL(err);		
       
  1077 		}
       
  1078 
       
  1079 	iLastError = KErrNone;
       
  1080 	StartCurrentClassController();
       
  1081  	}
       
  1082  	
       
  1083 TInt CUsbDevice::CurrentPersonalityId() const
       
  1084 /**
       
  1085  * @return the current personality id
       
  1086  */
       
  1087  	{
       
  1088 	LOG_FUNC
       
  1089  	return iCurrentPersonality->PersonalityId();
       
  1090  	}
       
  1091  	
       
  1092 const RPointerArray<CPersonality>& CUsbDevice::Personalities() const
       
  1093 /**
       
  1094  * @return a const reference to RPointerArray<CPersonality>
       
  1095  */
       
  1096  	{
       
  1097 	LOG_FUNC
       
  1098  	return iSupportedPersonalities;
       
  1099  	} 
       
  1100  	
       
  1101 const CPersonality* CUsbDevice::GetPersonality(TInt aPersonalityId) const
       
  1102 /**
       
  1103  * Obtains a handle to the CPersonality object whose id is aPersonalityId
       
  1104  *
       
  1105  * @param aPeraonalityId a personality id
       
  1106  * @return a const pointer to the CPersonality object whose id is aPersonalityId if found
       
  1107  * or 0 otherwise.
       
  1108  */
       
  1109 	{
       
  1110 	LOG_FUNC
       
  1111 	
       
  1112 	TInt count = iSupportedPersonalities.Count();
       
  1113 	for (TInt i = 0; i < count; i++)
       
  1114 		{
       
  1115 		if (iSupportedPersonalities[i]->PersonalityId() == aPersonalityId)
       
  1116 			{
       
  1117 			return iSupportedPersonalities[i];
       
  1118 			}
       
  1119 		}
       
  1120 	
       
  1121 	return 0;
       
  1122 	}
       
  1123 	
       
  1124 void CUsbDevice::SetCurrentPersonalityL(TInt aPersonalityId)
       
  1125 /**
       
  1126  * Sets the current personality to the personality with id aPersonalityId
       
  1127  */
       
  1128  	{
       
  1129 	LOG_FUNC
       
  1130 	const CPersonality* personality = GetPersonality(aPersonalityId);
       
  1131 	if (!personality)
       
  1132 		{
       
  1133 		LOGTEXT(_L8("Personality id not found"));
       
  1134 		LEAVEL(KErrNotFound);
       
  1135 		}
       
  1136 		
       
  1137 	iCurrentPersonality = personality;
       
  1138  	}
       
  1139 	
       
  1140 void CUsbDevice::ValidatePersonalitiesL()
       
  1141 /**
       
  1142  * Verifies all class controllers associated with each personality are loaded.
       
  1143  * Leave if validation fails.
       
  1144  */
       
  1145 	{
       
  1146 	LOG_FUNC
       
  1147 
       
  1148 	TInt personalityCount = iSupportedPersonalities.Count();
       
  1149 	for (TInt i = 0; i < personalityCount; i++)
       
  1150 		{
       
  1151 		const RArray<TUid>& classUids = iSupportedPersonalities[i]->SupportedClasses();
       
  1152 		TInt uidCount = classUids.Count();
       
  1153 		for (TInt j = 0; j < uidCount; j++)	
       
  1154 			{
       
  1155 			TInt ccCount = iSupportedClassUids.Count();
       
  1156 			TInt k;
       
  1157 			for (k = 0; k < ccCount; k++)
       
  1158 				{
       
  1159 				if (iSupportedClassUids[k] == classUids[j])
       
  1160 					{
       
  1161 					break;
       
  1162 					}
       
  1163 				}
       
  1164 			if (k == ccCount)
       
  1165 				{
       
  1166 				LOGTEXT(_L8("personality validation failed"));
       
  1167 				LEAVEL(KErrAbort);
       
  1168 				}					
       
  1169 			}	
       
  1170 		}
       
  1171 	}
       
  1172 /**
       
  1173 Converts text string with UIDs to array of Uint
       
  1174 
       
  1175 If there is an error during the conversion, this function will not clean-up,
       
  1176 so there may still be UIDs allocated in the RArray.
       
  1177 
       
  1178 @param aStr Reference to a string containing one or more UIDs in hex
       
  1179 @param aUIDs On return array of UIDs parsed from the input string
       
  1180 @panic EUidArrayNotEmpty if the RArray passed in is not empty
       
  1181 */
       
  1182 void CUsbDevice::ConvertUidsL(const TDesC& aStr, RArray<TUint>& aUidArray)	
       
  1183 	{
       
  1184 	// Function assumes that aUIDs is empty
       
  1185 	__ASSERT_DEBUG( aUidArray.Count() == 0, _USB_PANIC(KUsbDevicePanicCategory, EUidArrayNotEmpty) );
       
  1186 
       
  1187 	TLex input(aStr);
       
  1188 
       
  1189 	// Scan through string to find UIDs
       
  1190 	// Need to do this at least once, as no UID in the string is an error
       
  1191 	do 
       
  1192 		{
       
  1193 		// Find first hex digit
       
  1194 		while (!(input.Eos() || input.Peek().IsHexDigit()))
       
  1195 			{
       
  1196 			input.Inc();	
       
  1197 			}
       
  1198 
       
  1199 		// Convert and add to array
       
  1200 		TUint val;
       
  1201 		LEAVEIFERRORL(input.Val(val,EHex));
       
  1202 		aUidArray.AppendL(val);
       
  1203 		}
       
  1204 	while (!input.Eos());	
       
  1205 	}
       
  1206 
       
  1207 void CUsbDevice::ReadPersonalitiesL()
       
  1208 /**
       
  1209  * Reads configured personalities from the resource file
       
  1210  */
       
  1211 	{
       
  1212 	LOG_FUNC
       
  1213 	iPersonalityCfged = EFalse;
       
  1214 	// Now try to connect to file server
       
  1215 	RFs fs;
       
  1216 	LEAVEIFERRORL(fs.Connect());
       
  1217 	CleanupClosePushL(fs);
       
  1218 
       
  1219 	TFileName resourceFileName;
       
  1220 	ResourceFileNameL(resourceFileName);
       
  1221 	RResourceFile resource;
       
  1222 	TRAPD(err, resource.OpenL(fs, resourceFileName));
       
  1223 	LOGTEXT2(_L8("Opened resource file with error %d"), err);
       
  1224 
       
  1225 	if (err != KErrNone)
       
  1226 		{
       
  1227 		LOGTEXT(_L8("Unable to open resource file"));
       
  1228 		CleanupStack::PopAndDestroy(&fs);
       
  1229 		return;
       
  1230 		}
       
  1231 
       
  1232 	CleanupClosePushL(resource);
       
  1233 
       
  1234 	TInt resourceVersion = resource.SignatureL();
       
  1235 	LOGTEXT2(_L8("Resource file signature is %d"), resourceVersion);
       
  1236 	// Check for the version is valid(EUsbManagerResourceVersionOne, EUsbManagerResourceVersionTwo
       
  1237 	// or EUsbManagerResourceVersionThree).
       
  1238 	if(resourceVersion > EUsbManagerResourceVersionThree)
       
  1239 		{
       
  1240 		LOGTEXT2(_L8("Version of resource file is valid (>%d)"), EUsbManagerResourceVersionThree);
       
  1241 		User::LeaveIfError(KErrNotSupported);
       
  1242 		}
       
  1243 	
       
  1244 	resource.ConfirmSignatureL(resourceVersion);
       
  1245 
       
  1246 	HBufC8* personalityBuf = 0;
       
  1247 	TRAPD(ret, personalityBuf = resource.AllocReadL(DEVICE_PERSONALITIES));
       
  1248 	// If personalities resource is not found, swallow the error and return
       
  1249 	// as no specified personalities is a valid configuration
       
  1250 	if (ret == KErrNotFound)
       
  1251 		{
       
  1252 		LOGTEXT(_L8("Personalities are not configured"));
       
  1253 		CleanupStack::PopAndDestroy(2, &fs); 
       
  1254 		return;
       
  1255 		}
       
  1256 	// Otherwise leave noisily if the AllocRead fails
       
  1257 	LEAVEIFERRORL(ret);
       
  1258 	CleanupStack::PushL(personalityBuf);
       
  1259 
       
  1260 	// The format of the USB resource structure is:
       
  1261 	//
       
  1262 	// 	STRUCT PERSONALITY
       
  1263 	//		{
       
  1264 	// 		WORD	bcdDeviceClass;
       
  1265 	// 		WORD	bcdDeviceSubClass;
       
  1266 	//		WORD 	protocol;
       
  1267 	//		WORD	numConfigurations;
       
  1268 	//		WORD 	vendorId;
       
  1269 	//		WORD 	productId;
       
  1270 	//		WORD 	bcdDevice;
       
  1271 	//		LTEXT 	manufacturer;
       
  1272 	//		LTEXT 	product;
       
  1273 	//		WORD 	id;					// personality id
       
  1274 	//		LTEXT	class_uids;	
       
  1275 	//		LTEXT 	description;		// personality description
       
  1276 	//     	LTEXT   detailedDescription;  //detailed description. This is in version 2
       
  1277 	//		LONG 	Property;
       
  1278 	//		}
       
  1279 	//
       
  1280 	// Note that the resource must be read in this order!
       
  1281 	
       
  1282 	TResourceReader reader;
       
  1283 	reader.SetBuffer(personalityBuf);
       
  1284 
       
  1285 	TUint16 personalityCount 	= static_cast<TUint16>(reader.ReadUint16());
       
  1286 	
       
  1287 	// Read the manufacturer and device name (product) here from SysUtil class
       
  1288 	TPtrC16 sysUtilModelName;
       
  1289 	TPtrC16 sysUtilManuName;
       
  1290 
       
  1291 	// This method returns ownership.
       
  1292 	CDeviceTypeInformation* deviceInfo = SysUtil::GetDeviceTypeInfoL();
       
  1293 	CleanupStack::PushL(deviceInfo);
       
  1294 	TInt gotSysUtilModelName = deviceInfo->GetModelName(sysUtilModelName);
       
  1295 	TInt gotSysUtilManuName = deviceInfo->GetManufacturerName(sysUtilManuName);
       
  1296 	
       
  1297 	for (TInt idx = 0; idx < personalityCount; idx++)
       
  1298 		{
       
  1299 		// read a personality 
       
  1300 		TUint8 	bDeviceClass 		= static_cast<TUint8>(reader.ReadUint8());
       
  1301 		TUint8 	bDeviceSubClass 	= static_cast<TUint8>(reader.ReadUint8());
       
  1302 		TUint8 	protocol 			= static_cast<TUint8>(reader.ReadUint8());
       
  1303 		TUint8 	numConfigurations	= static_cast<TUint8>(reader.ReadUint8());
       
  1304 		TUint16 vendorId			= static_cast<TUint16>(reader.ReadUint16());
       
  1305 		TUint16 productId			= static_cast<TUint16>(reader.ReadUint16());
       
  1306 		TUint16 bcdDevice			= static_cast<TUint16>(reader.ReadUint16());
       
  1307 		TPtrC	manufacturer		= reader.ReadTPtrC();
       
  1308 		TPtrC	product				= reader.ReadTPtrC();
       
  1309 		TUint16 id					= static_cast<TUint16>(reader.ReadUint16());
       
  1310 		TPtrC	uidsStr				= reader.ReadTPtrC();
       
  1311 		TPtrC 	description			= reader.ReadTPtrC();
       
  1312 		
       
  1313 		RArray<TUint> uids;
       
  1314 		CleanupClosePushL(uids);
       
  1315 		ConvertUidsL(uidsStr, uids);
       
  1316 		// creates a CPersonality object
       
  1317 		CPersonality* personality = CPersonality::NewL();
       
  1318 		CleanupStack::PushL(personality);
       
  1319 
       
  1320 		personality->SetVersion(resourceVersion);
       
  1321 		
       
  1322 		// populates personality object
       
  1323 		personality->SetId(id);
       
  1324 		        
       
  1325 		for (TInt uidIdx = 0; uidIdx < uids.Count(); uidIdx++)
       
  1326 			{
       
  1327 			LEAVEIFERRORL(personality->AddSupportedClasses(TUid::Uid(uids[uidIdx])));
       
  1328 			}
       
  1329 		
       
  1330 		// gets a handle to iDeviceDescriptor of personality
       
  1331 		CUsbDevice::TUsbDeviceDescriptor& dvceDes = personality->DeviceDescriptor();
       
  1332 		if (gotSysUtilManuName == KErrNone)
       
  1333 			{
       
  1334 			personality->SetManufacturer(&sysUtilManuName);
       
  1335 			}
       
  1336 		else
       
  1337 			{
       
  1338 			personality->SetManufacturer(&manufacturer);
       
  1339 			}
       
  1340 			
       
  1341 		if (gotSysUtilModelName == KErrNone)
       
  1342 			{
       
  1343 			personality->SetProduct(&sysUtilModelName);
       
  1344 			}
       
  1345 		else
       
  1346 			{
       
  1347 			personality->SetProduct(&product);
       
  1348 			}
       
  1349 			
       
  1350 		personality->SetDescription(&description);
       
  1351 		dvceDes.iDeviceClass = bDeviceClass;
       
  1352 		dvceDes.iDeviceSubClass = bDeviceSubClass;
       
  1353 		dvceDes.iDeviceProtocol = protocol;
       
  1354 		dvceDes.iIdVendor = vendorId;
       
  1355 		dvceDes.iIdProduct= productId;
       
  1356 		dvceDes.iBcdDevice = bcdDevice;
       
  1357 		dvceDes.iNumConfigurations = numConfigurations;
       
  1358 		
       
  1359 		//detailedDescription is only supported after EUsbManagerResourceVersionTwo
       
  1360 		if(resourceVersion >= EUsbManagerResourceVersionTwo)
       
  1361 			{
       
  1362 			TPtrC   detailedDescription = reader.ReadTPtrC();        
       
  1363 			personality->SetDetailedDescription(&detailedDescription);
       
  1364 #ifdef __FLOG_ACTIVE
       
  1365 			TBuf8<KUsbDescMaxSize_String> narrowLongBuf;
       
  1366 			narrowLongBuf.Copy(detailedDescription);
       
  1367 			LOGTEXT2(_L8("detailed description = '%S'"),        &narrowLongBuf);            
       
  1368 #endif // __FLOG_ACTIVE
       
  1369 			}
       
  1370 
       
  1371 		//Property is only supported after EUsbManagerResourceVersionThree
       
  1372 		if(resourceVersion >= EUsbManagerResourceVersionThree)
       
  1373 			{
       
  1374 			TUint32 property			= static_cast<TUint32>(reader.ReadUint32());
       
  1375 			personality->SetProperty(property);
       
  1376 #ifdef __FLOG_ACTIVE
       
  1377 		LOGTEXT2(_L8("property = %d\n"), 			property);
       
  1378 #endif // __FLOG_ACTIVE
       
  1379 			}
       
  1380 		
       
  1381 		// Append personality to iSupportedPersonalities
       
  1382 		iSupportedPersonalities.AppendL(personality);
       
  1383 		// Now pop off personality
       
  1384 		CleanupStack::Pop(personality);
       
  1385 #ifdef __FLOG_ACTIVE
       
  1386 		// Debugging
       
  1387 		LOGTEXT2(_L8("personalityCount = %d\n"), 	personalityCount);
       
  1388 		LOGTEXT2(_L8("bDeviceClass = %d\n"), 		bDeviceClass);
       
  1389 		LOGTEXT2(_L8("bDeviceSubClass = %d\n"), 	bDeviceSubClass);
       
  1390 		LOGTEXT2(_L8("protocol = %d\n"), 			protocol);
       
  1391 		LOGTEXT2(_L8("numConfigurations = %d\n"), 	numConfigurations);
       
  1392 		LOGTEXT2(_L8("vendorId = %d\n"), 			vendorId);
       
  1393 		LOGTEXT2(_L8("productId = %d\n"), 			productId);
       
  1394 		LOGTEXT2(_L8("bcdDevice = %d\n"), 			bcdDevice);
       
  1395 		TBuf8<KMaxName> narrowBuf;
       
  1396 		narrowBuf.Copy(manufacturer);
       
  1397 		LOGTEXT2(_L8("manufacturer = '%S'"), 		&narrowBuf);
       
  1398 		narrowBuf.Copy(product);
       
  1399 		LOGTEXT2(_L8("product = '%S'"), 			&narrowBuf);
       
  1400 		LOGTEXT2(_L8("id = %d\n"), 					id);
       
  1401 		LOGTEXT(_L8("ClassUids{"));
       
  1402 		for (TInt k = 0; k < uids.Count(); k++)
       
  1403 			{
       
  1404 			LOGTEXT2(_L8("%d"), uids[k]);
       
  1405 			}
       
  1406 		LOGTEXT(_L8("}"));
       
  1407 		narrowBuf.Copy(description);
       
  1408 		LOGTEXT2(_L8("description = '%S'"), 		&narrowBuf);
       
  1409 #endif // __FLOG_ACTIVE
       
  1410 		CleanupStack::PopAndDestroy(&uids);	// close uid array		
       
  1411 		}
       
  1412 		
       
  1413 	CleanupStack::PopAndDestroy(4, &fs); // deviceInfo, personalityBuf, resource, fs
       
  1414 	iPersonalityCfged = ETrue;	
       
  1415 	}
       
  1416 	
       
  1417 void CUsbDevice::SelectClassControllersL()
       
  1418 /**
       
  1419  * Selects class controllers for the current personality
       
  1420  */
       
  1421 	{
       
  1422 	LOG_FUNC
       
  1423 
       
  1424 	CreateClassControllersL(iCurrentPersonality->SupportedClasses());
       
  1425 	}
       
  1426 #ifdef USE_DUMMY_CLASS_CONTROLLER	
       
  1427 void CUsbDevice::CreateClassControllersL(const RArray<TUid>& /* aClassUids*/)
       
  1428 #else 
       
  1429 void CUsbDevice::CreateClassControllersL(const RArray<TUid>& aClassUids)
       
  1430 #endif
       
  1431 /**
       
  1432  * Creates a class controller object for each class uid
       
  1433  *
       
  1434  * @param aClassUids an array of class uids
       
  1435  */
       
  1436  	{
       
  1437 	LOG_FUNC
       
  1438 
       
  1439 #ifndef USE_DUMMY_CLASS_CONTROLLER
       
  1440 
       
  1441 	//create a TLinearOrder to supply the comparison function, Compare(), to be used  
       
  1442 	//to determine the order to add class controllers
       
  1443 	TLinearOrder<CUsbClassControllerBase> order(CUsbClassControllerBase::Compare);
       
  1444 
       
  1445 	TInt count = aClassUids.Count();
       
  1446 	
       
  1447 	// destroy any class controller objects in iSupportedClasses and reset it for reuse
       
  1448 	iSupportedClasses.ResetAndDestroy();
       
  1449 	LOGTEXT2(_L8("aClassUids.Count() = %d\n"), 	count);
       
  1450 	for (TInt i = 0; i < count; i++)
       
  1451 		{ 
       
  1452 		CUsbClassControllerPlugIn* plugIn = CUsbClassControllerPlugIn::NewL(aClassUids[i], *this);
       
  1453 		AddClassControllerL(reinterpret_cast<CUsbClassControllerBase*>(plugIn), order);
       
  1454 		} 
       
  1455 #endif // USE_DUMMY_CLASS_CONTROLLER	
       
  1456 
       
  1457 	LEAVEIFERRORL(iUsbClassControllerIterator->First());
       
  1458  	}
       
  1459 
       
  1460 void CUsbDevice::SetDefaultPersonalityL()
       
  1461 /**
       
  1462  * Sets default personality. Used for Start request.
       
  1463  */
       
  1464 	{
       
  1465 	LOG_FUNC
       
  1466 
       
  1467 	TInt smallestId = iSupportedPersonalities[0]->PersonalityId();
       
  1468  	TInt count = iSupportedPersonalities.Count();
       
  1469  	
       
  1470  	for (TInt i = 1; i < count; i++)
       
  1471  		{
       
  1472  		if(iSupportedPersonalities[i]->PersonalityId() < smallestId)
       
  1473  			{
       
  1474  			smallestId = iSupportedPersonalities[i]->PersonalityId();
       
  1475  			}
       
  1476  		}
       
  1477 
       
  1478 	SetCurrentPersonalityL(smallestId);
       
  1479 	SelectClassControllersL();
       
  1480 	}
       
  1481 
       
  1482 void CUsbDevice::LoadFallbackClassControllersL()
       
  1483 /**
       
  1484  * Load class controllers for fallback situation:
       
  1485  * no personalities are configured.
       
  1486  * This method inserts all class controllers to 
       
  1487  * the list from which they will be either all started
       
  1488  * or stopped
       
  1489  */
       
  1490  	{
       
  1491 	LOG_FUNC
       
  1492  	SetDeviceDescriptorL();
       
  1493 	CreateClassControllersL(iSupportedClassUids);
       
  1494  	}
       
  1495  	
       
  1496 void CUsbDevice::ResourceFileNameL(TFileName& aFileName)
       
  1497 /**
       
  1498  * Gets resource file name
       
  1499  *
       
  1500  * @param aFileName Descriptor to populate with resource file name
       
  1501  */
       
  1502  	{
       
  1503 	LOG_FUNC
       
  1504 
       
  1505 	RFs fs;
       
  1506 	LEAVEIFERRORL(fs.Connect());
       
  1507 	CleanupClosePushL(fs);
       
  1508 
       
  1509 #ifdef __WINS__
       
  1510 	// If we are running in the emulator then read the resource file from system drive.
       
  1511 	// This makes testing with different resource files easier.
       
  1512 	_LIT(KPrivatePath, ":\\Private\\101fe1db\\");
       
  1513 	aFileName.Append(RFs::GetSystemDriveChar()); //get the name of system drive
       
  1514 	aFileName.Append(KPrivatePath);
       
  1515 #else
       
  1516  	const TDriveNumber KResourceDrive = EDriveZ;
       
  1517 
       
  1518 	TDriveUnit driveUnit(KResourceDrive);
       
  1519 	TDriveName drive=driveUnit.Name();
       
  1520 	aFileName.Insert(0, drive);
       
  1521 	// append private path
       
  1522 	TPath privatePath;
       
  1523 	fs.PrivatePath(privatePath);
       
  1524 	aFileName.Append(privatePath);		
       
  1525 #endif //WINS
       
  1526 
       
  1527 	// Find the nearest match of resource file for the chosen locale
       
  1528 	aFileName.Append(_L("usbman.rsc"));
       
  1529 	BaflUtils::NearestLanguageFile(fs, aFileName); // if a match is not found, usbman.rsc will be used
       
  1530 
       
  1531 	CleanupStack::PopAndDestroy(&fs);	// fs no longer needed
       
  1532  	}
       
  1533 
       
  1534 RDevUsbcClient& CUsbDevice::MuepoDoDevUsbcClient()
       
  1535 /**
       
  1536  * Inherited from MUsbmanExtensionPluginObserver - Function used by plugins to
       
  1537  * retrieve our handle to the LDD
       
  1538  *
       
  1539  * @return The LDD handle
       
  1540  */
       
  1541 	{
       
  1542 	return iLdd;
       
  1543 	}
       
  1544 
       
  1545 void CUsbDevice::MuepoDoRegisterStateObserverL(MUsbDeviceNotify& aObserver)
       
  1546 /**
       
  1547  * Inherited from MUsbmanExtensionPluginObserver - Function used by plugins to
       
  1548  * register themselves for notifications of device/service state changes.
       
  1549  *
       
  1550  * @param aObserver New Observer of the device
       
  1551  */
       
  1552 	{
       
  1553 	LOGTEXT2(_L8("CUsbDevice::MuepoDoRegisterStateObserverL aObserver = 0x%08x"),&aObserver);
       
  1554 	RegisterObserverL(aObserver);
       
  1555 	}