os/kernelhwsrv/kernel/eka/drivers/usbcc/ps_usbc.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32/drivers/usbcc/ps_usbc.cpp
    15 // Platform independent layer (PIL) of the USB Device controller driver (PDD).
    16 // Interface to the USB LDD.
    17 // 
    18 //
    19 
    20 /**
    21  @file ps_usbc.cpp
    22  @internalTechnology
    23 */
    24 
    25 #include <drivers/usbc.h>
    26 
    27 
    28 /**
    29 	TUsbcInterfaceSet and TUsbcInterface
    30 	====================================
    31 
    32 	TUsbcInterfaceSet represents a 'USB Interface' and TUsbcInterface
    33 	represents an 'Alternate Setting of a USB Interface'.
    34 
    35 	Since every LDD governs exactly one interface, the above distinction is
    36 	made only within the USB implementation. At the LDD API, there is/are
    37 	simply one or more settings for this single interface, numbered from '0'
    38 	(the default) to 'n', and specified by the parameter 'TInt aInterfaceNum'.
    39 
    40 	Within the PDD implementation, for a TUsbcInterfaceSet number the parameter
    41 	'TInt aIfcSet' is used (local variable ifcset); for a TUsbcInterface number
    42 	the parameter 'TInt aIfc' is used (local variable ifc).
    43 
    44 
    45 	iConfigs[0] and CurrentConfig()
    46 	===============================
    47 
    48 	One problem with this file is that it always uses iConfigs[0] and not
    49 	CurrentConfig(). This is mainly because the API to the LDD doesn't know
    50 	about the concept of multiple configurations, and thus always assumes one
    51 	single configuration (which is also always active: a further problem).
    52 
    53 	In the file chapter9.cpp this issue doesn't exist, since there we always
    54 	have to obey the USB protocol, and in this way will use the configuration
    55 	which is selected by the host (which will then again currently always be
    56 	iConfigs[0].)
    57 
    58 
    59 	iEp0ClientId and iEp0DataReceiving
    60 	==================================
    61 
    62 	The purpose of these two members of class DUsbClientController is the
    63 	following.
    64 
    65 	They are used only during Ep0 control transactions which have an OUT (Rx)
    66 	data stage. The special problem with these transactions is twofold. For one
    67 	thing we have to know that what we are receiving is data and not a Setup
    68 	packet. Furthermore we cannot deduce from the received data itself to whom
    69 	it is addressed (that's because of the shared nature of Ep0).
    70 
    71 	So in order to recognize data packets we use iEp0DataReceiving. This
    72 	variable is set to TRUE either 1) upon processing a standard request which
    73 	has a DATA_OUT phase (only SET_DESCRIPTOR), or 2) if we have identified a
    74 	class-specific request which has a DATA_OUT phase and we have also found
    75 	the recipient for that request.
    76 
    77 	In order to be able to tell whether received Ep0 data is to be processed by
    78 	the PIL or a LDD, we use iEp0ClientId. iEp0ClientId is usually NULL, which
    79 	means it is our data. However it is set to the client ID of an LDD in case
    80 	2) above. That way we can subsequently hand over received data to the
    81 	correct client LDD.
    82 
    83 	iEp0DataReceived tracks the amount of data already received - it is used to
    84 	determine the end of the DATA_OUT phase, irrespective of the owner of the
    85 	data. The total amount that is to be received can be obtained via
    86 	iSetup.iLength. (iSetup holds in that case the Setup packet of the current
    87 	Control transfer.)
    88 
    89 	iEp0ClientDataTransmitting is only set to TRUE if a client sets up an Ep0
    90 	write. After that transmission has completed we use this value to decide
    91 	whether we have to report the completion to a client or not. (If this
    92 	variable is FALSE, we did set up the write and thus no client notification
    93 	is necessary.)
    94 
    95 */
    96 
    97 //
    98 // === Global and Local Variables ==================================================================
    99 //
   100 
   101 GLDEF_D DUsbClientController* DUsbClientController::UsbClientController[] = {NULL, NULL};
   102 
   103 static const TInt KUsbReconnectDelay   = 500;				// milliseconds
   104 static const TInt KUsbCableStatusDelay = 500;				// milliseconds
   105 
   106 
   107 //
   108 // === USB Controller member function implementations - LDD API (public) ===========================
   109 //
   110 
   111 
   112 /** The class destructor.
   113 
   114 	This rarely gets called, except, for example when something goes
   115 	wrong during construction.
   116 
   117 	It's not exported because it is virtual.
   118 */
   119 DUsbClientController::~DUsbClientController()
   120 	{
   121 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::~DUsbClientController()"));
   122 	if (iPowerHandler)
   123 		{
   124 		iPowerHandler->Remove();
   125 		delete iPowerHandler;
   126 		}
   127 	// ResetAndDestroy() will call for every array element the destructor of the pointed-to object,
   128 	// before deleting the element itself, and closing the array.
   129 	iConfigs.ResetAndDestroy();
   130 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::~DUsbClientController(): Done."));
   131 	}
   132 
   133 
   134 /** To be called by the OTG/Host stack in an OTG setup to disable USB device
   135 	functionality.
   136 
   137 	The OTG stack calls this function when VBus is no longer valid, when the
   138 	B-device swaps out of peripheral mode, or when moving out of the
   139 	A_PERIPHERAL state.
   140 
   141 	The Client stack will disable the D+ pull-up immediately when the function
   142 	is called.
   143 
   144 	During DisableClientStack() the Client stack will notify its registered
   145 	applications on the user-side (including the USB Manager) about a USB
   146 	device state change event, a transition to the "Undefined" state.
   147 */
   148 EXPORT_C void DUsbClientController::DisableClientStack()
   149 	{
   150 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DisableClientStack()"));
   151 	if (!iStackIsActive)
   152 		{
   153 		__KTRACE_OPT(KUSB, Kern::Printf("  Already disabled - returning"));
   154 		return;
   155 		}
   156 	iOtgClientConnect = EFalse;
   157 	TInt r = EvaluateOtgConnectFlags();					 // will disconnect UDC
   158 	if (r != KErrNone)
   159 		{
   160 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: EvaluateOtgConnectFlags() failed: %d", r));
   161 		}
   162 
   163 	// Reset OTG features, leave attributes as is (just as in USB Reset case)
   164 	// (OTG spec 1.3 sections 6.5.x all say "... on a bus reset or at the end
   165 	//  of a session." VBus drop is the end of a session.)
   166 	iOtgFuncMap &= KUsbOtgAttr_SrpSupp | KUsbOtgAttr_HnpSupp;
   167 	OtgFeaturesNotify();
   168 	// Tear down the current configuration (if any)
   169 	ChangeConfiguration(0);
   170 
   171 	if (iDeviceState != EUsbcDeviceStateUndefined)
   172 		{
   173 		// Not being in state UNDEFINED implies that the cable is inserted.
   174 		if (iHardwareActivated)
   175 			{
   176 			NextDeviceState(EUsbcDeviceStatePowered);
   177 			}
   178 		// (If the hardware is NOT activated at this point, we can only be in
   179 		//	state EUsbcDeviceStateAttached, so we don't have to move to it.)
   180 		}
   181 	DeActivateHardwareController();					 // turn off UDC altogether
   182 	iStackIsActive = EFalse;
   183 	// Complete all pending requests, returning KErrDisconnected
   184 	RunClientCallbacks();
   185 	// Notify registered clients on the user side about a USB device state
   186 	// change event and a transition to the "Undefined" state.
   187 	NextDeviceState(EUsbcDeviceStateUndefined);
   188 	}
   189 
   190 
   191 /** To be called by the OTG/Host stack in an OTG setup to enable USB device
   192 	functionality.
   193 
   194 	Once called, the function will return quickly, but it will by then not
   195 	necessarily have enabled the D+ pull-up*. The Client stack can enable the D+
   196 	pull-up (via the transceiver) from that moment on and as long as the OTG
   197 	stack doesn't call DisableClientStack().
   198 
   199 	*) It will enable the D+ pull-up immediately if the user-side USB support
   200 	has already been loaded. This should always be the case when the OTG stack
   201 	is calling this function during the transition to the A_PERIPHERAL state,
   202 	i.e. when acting as an A-device.
   203 */
   204 EXPORT_C void DUsbClientController::EnableClientStack()
   205 	{
   206 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnableClientStack()"));
   207 	if (iStackIsActive)
   208 		{
   209 		__KTRACE_OPT(KUSB, Kern::Printf("  Already enabled - returning"));
   210 		return;
   211 		}
   212 	iStackIsActive = ETrue;
   213 	// If the UDC is still off, we switch it on here.
   214 	TInt r = ActivateHardwareController();
   215 	if (r != KErrNone)
   216 		{
   217 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: ActivateHardwareController() failed: %d", r));
   218 		}
   219 	iOtgClientConnect = ETrue;
   220 	r = EvaluateOtgConnectFlags();							// may connect UDC
   221 	if (r != KErrNone)
   222 		{
   223 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: EvaluateOtgConnectFlags() failed: %d", r));
   224 		}
   225 	}
   226 
   227 
   228 /** Called by LDD to see if controller is usable.
   229 
   230 	@return ETrue if controller is in normal state, EFalse if it is disabled.
   231 */
   232 EXPORT_C TBool DUsbClientController::IsActive()
   233 	{
   234 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::IsActive()"));
   235 	return iStackIsActive;
   236 	}
   237 
   238 
   239 /** Called by LDD to register client callbacks.
   240 
   241 	@return KErrNone if successful, KErrAlreadyExists callback exists.
   242 */
   243 EXPORT_C TInt DUsbClientController::RegisterClientCallback(TUsbcClientCallback& aCallback)
   244 	{
   245 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterClientCallback()"));
   246 	if (iClientCallbacks.Elements() == KUsbcMaxListLength)
   247 		{
   248 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
   249 										  KUsbcMaxListLength));
   250 		return KErrGeneral;
   251 		}
   252 	TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
   253 	TUsbcClientCallback* p;
   254 	while ((p = iter++) != NULL)
   255 		if (p == &aCallback)
   256 			{
   257 			__KTRACE_OPT(KUSB, Kern::Printf("	 Error: ClientCallback @ 0x%x already registered", &aCallback));
   258 			return KErrAlreadyExists;
   259 			}
   260 	iClientCallbacks.AddLast(aCallback);
   261 	return KErrNone;
   262 	}
   263 
   264 
   265 /** Returns a pointer to the USB client controller object.
   266 
   267 	This function is static.
   268 
   269 	@param aUdc The number of the UDC (0..n) for which the pointer is to be returned.
   270 
   271 	@return A pointer to the USB client controller object.
   272 */
   273 EXPORT_C DUsbClientController* DUsbClientController::UsbcControllerPointer(TInt aUdc)
   274 	{
   275 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbcControllerPointer()"));
   276 	if (aUdc < 0 || aUdc > 1)
   277 		{
   278 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: aUdc out of range (%d)", aUdc));
   279 		return NULL;
   280 		}
   281 	return UsbClientController[aUdc];
   282 	}
   283 
   284 
   285 /** Fills the buffer passed in as an argument with endpoint capability information.
   286 
   287  	@see DUsbClientController::DeviceCaps()
   288 	@see TUsbcEndpointData
   289 	@see TUsbDeviceCaps
   290 
   291 	@param aClientId A pointer to the LDD making the enquiry.
   292 	@param aCapsBuf A reference to a descriptor buffer, which, on return, contains an array of
   293 	TUsbcEndpointData elements; there are TUsbDeviceCaps::iTotalEndpoints elements in the array;
   294 	call DeviceCaps() to get the number of elements required.
   295 */
   296 EXPORT_C void DUsbClientController::EndpointCaps(const DBase* aClientId, TDes8& aCapsBuf) const
   297 	{
   298 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointCaps()"));
   299 	// Here we do not simply call DUsbClientController::DeviceEndpointCaps(),
   300 	// because that function fills an array which comprises of _all_ endpoints,
   301 	// whereas this function omits ep0 and all unusable endpoints.
   302 	// Apart from that, we have to fill an array of TUsbcEndpointData, not TUsbcEndpointCaps.
   303 	TUsbcEndpointData data[KUsbcMaxEndpoints];
   304 	const TInt ifcset_num = ClientId2InterfaceNumber(aClientId);
   305 	for (TInt i = 2, j = 0; i < iDeviceTotalEndpoints; ++i)
   306 		{
   307 		__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Caps: RealEndpoint #%d", i));
   308 		if (iRealEndpoints[i].iCaps.iTypesAndDir != KUsbEpNotAvailable)
   309 			{
   310 			__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Caps: --> UsableEndpoint #%d", j));
   311 			data[j].iCaps = iRealEndpoints[i].iCaps;
   312 			if (ifcset_num < 0)
   313 				{
   314 				// If this LDD doesn't own an interface, but the Ep points to one,
   315 				// then that must be the interface of a different LDD. Hence the Ep
   316 				// is not available for this LDD.
   317 				data[j].iInUse = (iRealEndpoints[i].iIfcNumber != NULL);
   318 				}
   319 			else
   320 				{
   321 				// If this LDD does already own an interface, and the Ep also points to one,
   322 				// then the Ep is not available for this LDD only if that interface is owned
   323 				// by a different LDD (i.e. if the interface number is different).
   324 				// Reason: Even though the endpoint might already be part of an interface setting,
   325 				// it is still available for a different alternate setting of the same interface.
   326 				data[j].iInUse = ((iRealEndpoints[i].iIfcNumber != NULL) &&
   327 								  (*(iRealEndpoints[i].iIfcNumber) != ifcset_num));
   328 				}
   329 			j++;
   330 			}
   331 		}
   332 	// aCapsBuf resides in userland
   333 	TPtrC8 des((TUint8*)data, sizeof(data));
   334 	const TInt r = Kern::ThreadDesWrite((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
   335 										&aCapsBuf, des, 0, KChunkShiftBy0, NULL);
   336 	if (r != KErrNone)
   337 		{
   338 		Kern::ThreadKill((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
   339 						 EExitPanic, r, KUsbPILKillCat);
   340 		}
   341 	}
   342 
   343 
   344 /** Fills the buffer passed in as an argument with device capability information.
   345 
   346 	@see TUsbDeviceCaps
   347 	@see TUsbDeviceCapsV01
   348 
   349 	@param aClientId A pointer to the LDD making the enquiry.
   350 	@param aCapsBuf A reference to a descriptor buffer which, on return, contains
   351 	a TUsbDeviceCaps structure.
   352 */
   353 EXPORT_C void DUsbClientController::DeviceCaps(const DBase* aClientId, TDes8& aCapsBuf) const
   354 	{
   355 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceCaps()"));
   356 	TUsbDeviceCaps caps;
   357 	caps().iTotalEndpoints = iDeviceUsableEndpoints;		// not DeviceTotalEndpoints()!
   358 	caps().iConnect = SoftConnectCaps();
   359 	caps().iSelfPowered = iSelfPowered;
   360 	caps().iRemoteWakeup = iRemoteWakeup;
   361 	caps().iHighSpeed = DeviceHighSpeedCaps();
   362 	caps().iFeatureWord1 = CableDetectWithoutPowerCaps() ?
   363 		caps().iFeatureWord1 | KUsbDevCapsFeatureWord1_CableDetectWithoutPower :
   364 		caps().iFeatureWord1 & ~KUsbDevCapsFeatureWord1_CableDetectWithoutPower;
   365 	caps().iFeatureWord1 = DeviceResourceAllocV2Caps() ?
   366 		caps().iFeatureWord1 | KUsbDevCapsFeatureWord1_EndpointResourceAllocV2 :
   367 		caps().iFeatureWord1 & ~KUsbDevCapsFeatureWord1_EndpointResourceAllocV2;
   368 	caps().iReserved = 0;
   369 
   370 	// aCapsBuf resides in userland
   371 	const TInt r = Kern::ThreadDesWrite((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
   372 										&aCapsBuf, caps, 0, KChunkShiftBy0, NULL);
   373 	if (r != KErrNone)
   374 		{
   375 		Kern::ThreadKill((reinterpret_cast<const DLddUsbcChannel*>(aClientId))->Client(),
   376 						 EExitPanic, r, KUsbPILKillCat);
   377 		}
   378 	}
   379 
   380 
   381 TUsbcEndpointInfoArray::TUsbcEndpointInfoArray(const TUsbcEndpointInfo* aData, TInt aDataSize)
   382 	{
   383 	iType = EUsbcEndpointInfo;
   384 	iData = (TUint8*) aData;
   385 	if (aDataSize > 0)
   386 		iDataSize = aDataSize;
   387 	else
   388 		iDataSize = sizeof(TUsbcEndpointInfo);
   389 	}
   390 
   391 
   392 inline TUsbcEndpointInfo& TUsbcEndpointInfoArray::operator[](TInt aIndex) const
   393 	{
   394 	return *(TUsbcEndpointInfo*) &iData[aIndex * iDataSize];
   395 	}
   396 
   397 
   398 EXPORT_C TInt DUsbClientController::SetInterface(const DBase* aClientId, DThread* aThread,
   399 												 TInt aInterfaceNum, TUsbcClassInfo& aClass,
   400 												 TDesC8* aString, TInt aTotalEndpointsUsed,
   401 												 const TUsbcEndpointInfo aEndpointData[],
   402 												 TInt (*aRealEpNumbers)[6], TUint32 aFeatureWord)
   403 	{
   404 	TUsbcEndpointInfoArray endpointData = TUsbcEndpointInfoArray(aEndpointData);
   405 	return SetInterface(aClientId, aThread, aInterfaceNum, aClass, aString, aTotalEndpointsUsed,
   406 						endpointData, (TInt*) aRealEpNumbers, aFeatureWord);
   407 	}
   408 
   409 
   410 /** Creates a new USB interface (one setting), complete with endpoints, descriptors, etc.,
   411 	and chains it into the internal device configuration tree.
   412 
   413 	@param aClientId A pointer to the LDD owning the new interface.
   414 	@param aThread A pointer to the thread the owning LDD is running in.
   415 	@param aInterfaceNum The interface setting number of the new interface setting. This must be 0
   416 	if it is the first setting of the interface that gets created, or 1 more than the last setting
   417 	that was created for this interface.
   418 	@param aClass Contains information about the device class this interface might belong to.
   419 	@param aString A pointer to a string that is used for the string descriptor of this interface.
   420 	@param aTotalEndpointsUsed The number of endpoints used by this interface (and also the number of
   421 	elements of the following array).
   422 	@param aEndpointData An array with aTotalEndpointsUsed elements, containing information about the
   423 	endpoints of this interface.
   424 
   425 	@return KErrNotSupported if Control endpoints are requested by the LDD but aren't supported by the PIL,
   426 	KErrInUse if at least one requested endpoint is - temporarily or permanently - not available for use,
   427 	KErrNoMemory if (endpoint, interface, string) descriptor allocation fails, KErrGeneral if something else
   428 	goes wrong during endpoint or interface or descriptor creation, KErrNone if interface successfully set up.
   429 */
   430 EXPORT_C TInt DUsbClientController::SetInterface(const DBase* aClientId, DThread* aThread,
   431 												 TInt aInterfaceNum, TUsbcClassInfo& aClass,
   432 												 TDesC8* aString, TInt aTotalEndpointsUsed,
   433 												 const TUsbcEndpointInfoArray aEndpointData,
   434 												 TInt aRealEpNumbers[], TUint32 aFeatureWord)
   435 	{
   436 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetInterface()"));
   437 	if (aInterfaceNum != 0)
   438 		{
   439 		__KTRACE_OPT(KUSB, Kern::Printf("  alternate interface setting request: #%d", aInterfaceNum));
   440 		}
   441 #ifndef USB_SUPPORTS_CONTROLENDPOINTS
   442 	for (TInt i = 0; i < aTotalEndpointsUsed; ++i)
   443 		{
   444 		if (aEndpointData[i].iType == KUsbEpTypeControl)
   445 			{
   446 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: control endpoints not supported"));
   447 			return KErrNotSupported;
   448 			}
   449 		}
   450 #endif
   451 	// Check for endpoint availability & check those endpoint's capabilities
   452 	const TInt ifcset_num = ClientId2InterfaceNumber(aClientId);
   453 	// The passed-in ifcset_num may be -1 now, but that's intended.
   454 	if (!CheckEpAvailability(aTotalEndpointsUsed, aEndpointData, ifcset_num))
   455 		{
   456 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: endpoints not (all) available"));
   457 		return KErrInUse;
   458 		}
   459 	// Create & setup new interface
   460 	TUsbcInterface* ifc = CreateInterface(aClientId, aInterfaceNum, aFeatureWord);
   461 	if (ifc == NULL)
   462 		{
   463 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: ifc == NULL"));
   464 		return KErrGeneral;
   465 		}
   466 	// Create logical endpoints
   467 	TInt r = CreateEndpoints(ifc, aTotalEndpointsUsed, aEndpointData, aRealEpNumbers);
   468 	if (r != KErrNone)
   469 		{
   470 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: CreateEndpoints() != KErrNone"));
   471 		DeleteInterface(ifc->iInterfaceSet->iInterfaceNumber, aInterfaceNum);
   472 		return r;
   473 		}
   474 	// Create & setup interface, string, and endpoint descriptors
   475 	r = SetupIfcDescriptor(ifc, aClass, aThread, aString, aEndpointData);
   476 	if (r != KErrNone)
   477 		{
   478 		return r;
   479 		}
   480 	return KErrNone;
   481 	}
   482 
   483 
   484 /** Releases an existing USB interface (one setting), complete with endpoints, descriptors, etc.,
   485 	and removes it from the internal device configuration tree.
   486 
   487 	@param aClientId A pointer to the LDD owning the interface.
   488 	@param aInterfaceNum The setting number of the interface setting to be deleted. This must be
   489 	the highest numbered (or 'last') setting for this interface.
   490 
   491 	@return KErrNotFound if interface (not setting) for some reason cannot be found, KErrArgument if an
   492 	invalid interface setting number is specified (not existing or existing but too small), KErrNone if
   493 	interface successfully released or if this client doesn't own any interface.
   494 */
   495 EXPORT_C TInt DUsbClientController::ReleaseInterface(const DBase* aClientId, TInt aInterfaceNum)
   496 	{
   497 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReleaseInterface(..., %d)", aInterfaceNum));
   498 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
   499 	if (ifcset < 0)
   500 		{
   501 		__KTRACE_OPT(KUSB, Kern::Printf(" interface not found")); // no error
   502 		return KErrNone;
   503 		}
   504 	TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
   505 	if (!ifcset_ptr)
   506 		{
   507 		__KTRACE_OPT(KUSB, Kern::Printf(" Error: interface number %d doesn't exist", ifcset));
   508 		return KErrNotFound;
   509 		}
   510 	const TInt setting_count = ifcset_ptr->iInterfaces.Count();
   511 	if ((setting_count - 1) != aInterfaceNum)
   512 		{
   513 		__KTRACE_OPT(KUSB,
   514 					 Kern::Printf(" > Error: interface settings must be released in descending order:\n\r"
   515 								  "   %d setting(s) exist, #%d was requested to be released.\n\r"
   516 								  "   (#%d has to be released first)",
   517 								  setting_count, aInterfaceNum, setting_count - 1));
   518 		return KErrArgument;
   519 		}
   520 	// Tear down current setting (invalidate configured state)
   521 	__KTRACE_OPT(KUSB, Kern::Printf(" > tearing down InterfaceSet %d", ifcset));
   522 	// Cancel all transfers on the current setting of this interface and deconfigure all its endpoints.
   523 	InterfaceSetTeardown(ifcset_ptr);
   524 	// 'Setting 0' means: delete all existing settings.
   525 	if (aInterfaceNum == 0)
   526 		{
   527 		TInt m = ifcset_ptr->iInterfaces.Count();
   528 		while (m > 0)
   529 			{
   530 			m--;
   531 			// Ground the physical endpoints' logical_endpoint_pointers
   532 			const TInt n = ifcset_ptr->iInterfaces[m]->iEndpoints.Count();
   533 			for (TInt i = 0; i < n; ++i)
   534 				{
   535 				TUsbcPhysicalEndpoint* ptr = const_cast<TUsbcPhysicalEndpoint*>
   536 					(ifcset_ptr->iInterfaces[m]->iEndpoints[i]->iPEndpoint);
   537 				ptr->iLEndpoint = NULL;
   538 				}
   539 			// Delete the setting itself + its ifc & ep descriptors
   540 			DeleteInterface(ifcset, m);
   541 			iDescriptors.DeleteIfcDescriptor(ifcset, m);
   542 			}
   543 		}
   544 	else
   545 		{
   546 		// Ground the physical endpoints' logical_endpoint_pointers
   547 		const TInt n = ifcset_ptr->iInterfaces[aInterfaceNum]->iEndpoints.Count();
   548 		for (TInt i = 0; i < n; ++i)
   549 			{
   550 			TUsbcPhysicalEndpoint* ptr = const_cast<TUsbcPhysicalEndpoint*>
   551 				(ifcset_ptr->iInterfaces[aInterfaceNum]->iEndpoints[i]->iPEndpoint);
   552 			ptr->iLEndpoint = NULL;
   553 			}
   554 		// Delete the setting itself + its ifc & ep descriptors
   555 		DeleteInterface(ifcset, aInterfaceNum);
   556 		iDescriptors.DeleteIfcDescriptor(ifcset, aInterfaceNum);
   557 		}
   558 	// Delete the whole interface if all settings are gone
   559 	if (ifcset_ptr->iInterfaces.Count() == 0)
   560 		{
   561 		DeleteInterfaceSet(ifcset);
   562 		}
   563 	// We now no longer have a valid current configuration
   564 	iCurrentConfig = 0;
   565 	if (iDeviceState == EUsbcDeviceStateConfigured)
   566 		{
   567 		NextDeviceState(EUsbcDeviceStateAddress);
   568 		}
   569 	// If it was the last interface(set)...
   570 	if (iConfigs[0]->iInterfaceSets.Count() == 0)
   571 		{
   572 		__KTRACE_OPT(KUSB, Kern::Printf("  No ifc left -> turning off UDC"));
   573 		// First disconnect the device from the bus
   574 		UsbDisconnect();
   575 		DeActivateHardwareController();
   576 		// (this also disables endpoint zero; we cannot have a USB device w/o interface, see 9.6.3)
   577 		}
   578 	return KErrNone;
   579 	}
   580 
   581 
   582 /** Enforces a USB re-enumeration by disconnecting the UDC from the bus (if it is currently connected) and
   583 	re-connecting it.
   584 
   585 	This only works if the PSL supports it, i.e. if SoftConnectCaps() returns ETrue.
   586 */
   587 EXPORT_C TInt DUsbClientController::ReEnumerate()
   588 	{
   589 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReEnumerate()"));
   590 	// If, in an OTG setup, the client stack is disabled, there's no point in
   591 	// trying to reenumerate the device. In fact, we then don't even want to
   592 	// turn on the UDC via ActivateHardwareController().
   593 	if (!iStackIsActive)
   594 		{
   595 		__KTRACE_OPT(KUSB, Kern::Printf("  Client stack disabled -> returning here"));
   596 		return KErrNotReady;
   597 		}
   598 	// We probably don't check here whether SoftConnectCaps() is ETrue, and
   599 	// return if not, because we might still want to execute
   600 	// ActivateHardwareController(). UsbConnect() and UsbDisconnect() should be
   601 	// no-ops if not supported by the PSL.
   602 	if (iConfigs[0]->iInterfaceSets.Count() == 0)
   603 		{
   604 		__KTRACE_OPT(KUSB, Kern::Printf("  > No interface registered -> no need to re-enumerate"));
   605 		return KErrNone;;
   606 		}
   607 	if (!iHardwareActivated)
   608 		{
   609 		// If the UDC is still off, we switch it on here.
   610 		const TInt r = ActivateHardwareController();
   611 		if (r != KErrNone)
   612 				{
   613 				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: ActivateHardwareController() failed: %d", r));
   614 				return r;
   615 				}
   616 		// Finally connect the device to the bus
   617 		UsbConnect();
   618 		}
   619 	else
   620 		{
   621 		UsbDisconnect();
   622 		// Now we have to wait a certain amount of time, in order to give the host the opportunity
   623 		// to come to terms with the new situation.
   624 		// (The ETrue parameter makes the callback get called in DFC instead of in ISR context.)
   625 		iReconnectTimer.OneShot(KUsbReconnectDelay, ETrue);
   626 		}
   627 	return KErrNone;;
   628 	}
   629 
   630 
   631 /** Powers up the UDC if one or more interfaces exist.
   632 
   633 	@return KErrNone if UDC successfully powered up, KErrNotReady if no
   634 	interfaces have been registered yet, KErrHardwareNotAvailable if UDC
   635 	couldn't be activated.
   636 */
   637 EXPORT_C TInt DUsbClientController::PowerUpUdc()
   638 	{
   639 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerUpUdc()"));
   640 	// If, in an OTG setup, the client stack is disabled, we mustn't turn on
   641 	// the UDC via ActivateHardwareController() as that would already configure
   642 	// Ep0.
   643 	if (!iStackIsActive)
   644 		{
   645 		__KTRACE_OPT(KUSB, Kern::Printf("  Client stack disabled -> returning here"));
   646 		return KErrNotReady;
   647 		}
   648 	if (iConfigs[0]->iInterfaceSets.Count() == 0)
   649 		{
   650 		__KTRACE_OPT(KUSB, Kern::Printf("  > No interface registered -> won't power up UDC"));
   651 		return KErrNotReady;
   652 		}
   653 	// If the UDC is still off, we switch it on here.
   654 	const TInt r = ActivateHardwareController();
   655 	if (r != KErrNone)
   656 		{
   657 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: ActivateHardwareController() failed: %d", r));
   658 		}
   659 	return r;
   660 	}
   661 
   662 
   663 /** Connects the UDC to the bus.
   664 
   665 	This only works if the PSL supports it, i.e. if SoftConnectCaps() returns ETrue.
   666 
   667 	@return KErrNone if UDC successfully connected, KErrGeneral if there was an error.
   668 */
   669 EXPORT_C TInt DUsbClientController::UsbConnect()
   670 	{
   671 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbConnect()"));
   672 #ifdef USB_OTG_CLIENT
   673 	iClientSupportReady = ETrue;
   674 	const TInt r = EvaluateOtgConnectFlags();
   675 	const TInt irq = NKern::DisableAllInterrupts();
   676 	if (iUsbResetDeferred) // implies (iOtgHnpHandledByHw == ETrue)
   677 		{
   678 		__KTRACE_OPT(KUSB, Kern::Printf("  Resetting USB Reset 'defer' flag"));
   679 		iUsbResetDeferred = EFalse;
   680 		(void) ProcessResetEvent(EFalse);
   681 		}
   682 	NKern::RestoreInterrupts(irq);
   683 #else
   684 	const TInt r = UdcConnect();
   685 #endif // USB_OTG_CLIENT
   686 	return r;
   687 	}
   688 
   689 
   690 /** Disconnects the UDC from the bus.
   691 
   692 	This only works if the PSL supports it, i.e. if SoftConnectCaps() returns ETrue.
   693 
   694 	@return KErrNone if UDC successfully disconnected, KErrGeneral if there was an error.
   695 */
   696 EXPORT_C TInt DUsbClientController::UsbDisconnect()
   697 	{
   698 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::UsbDisconnect()"));
   699 #ifdef USB_OTG_CLIENT
   700 	iClientSupportReady = EFalse;
   701 	const TInt r = EvaluateOtgConnectFlags();
   702 #else
   703 	const TInt r = UdcDisconnect();
   704 #endif // USB_OTG_CLIENT
   705 	// There won't be any notification by the PSL about this,
   706 	// so we have to notify the LDD/user ourselves:
   707 	if ((r == KErrNone) && (iDeviceState != EUsbcDeviceStateUndefined))
   708 		{
   709 		// Not being in state UNDEFINED implies that the cable is inserted.
   710 		if (iHardwareActivated)
   711 			{
   712 			NextDeviceState(EUsbcDeviceStatePowered);
   713 			}
   714 		// (If the hardware is NOT activated at this point, we can only be in
   715 		//	state EUsbcDeviceStateAttached, so we don't have to move to it.)
   716 		}
   717 	return r;
   718 	}
   719 
   720 
   721 /** Registers a notification callback for changes of the USB device state.
   722 
   723 	In the event of a device state change, the callback's state member gets updated (using SetState) with a
   724 	new TUsbcDeviceState value, and then the callback is executed (DoCallback). 'USB device state' here refers
   725 	to the Visible Device States as defined in chapter 9 of the USB specification.
   726 
   727 	@param aCallback A reference to a properly filled in status callback structure.
   728 
   729 	@return KErrNone if callback successfully registered, KErrGeneral if this callback is already registered
   730 	(it won't be registered twice).
   731 */
   732 EXPORT_C TInt DUsbClientController::RegisterForStatusChange(TUsbcStatusCallback& aCallback)
   733 	{
   734 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForStatusChange()"));
   735 	if (iStatusCallbacks.Elements() == KUsbcMaxListLength)
   736 		{
   737 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
   738 										  KUsbcMaxListLength));
   739 		return KErrGeneral;
   740 		}
   741 	if (IsInTheStatusList(aCallback))
   742 		{
   743 		__KTRACE_OPT(KUSB, Kern::Printf("  Error: StatusCallback @ 0x%x already registered", &aCallback));
   744 		return KErrGeneral;
   745 		}
   746 	const TInt irq = NKern::DisableAllInterrupts();
   747 	iStatusCallbacks.AddLast(aCallback);
   748 	NKern::RestoreInterrupts(irq);
   749 	return KErrNone;
   750 	}
   751 
   752 
   753 /** De-registers (removes from the list of pending requests) a notification callback for the USB device
   754 	status.
   755 
   756 	@param aClientId A pointer to the LDD owning the status change callback.
   757 
   758 	@return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
   759 */
   760 EXPORT_C TInt DUsbClientController::DeRegisterForStatusChange(const DBase* aClientId)
   761 	{
   762 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForStatusChange()"));
   763 	__ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
   764 	const TInt irq = NKern::DisableAllInterrupts();
   765 	TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks);
   766 	TUsbcStatusCallback* p;
   767 	while ((p = iter++) != NULL)
   768 		{
   769 		if (p->Owner() == aClientId)
   770 			{
   771 			__KTRACE_OPT(KUSB, Kern::Printf("  removing StatusCallback @ 0x%x", p));
   772 			iStatusCallbacks.Remove(*p);
   773 			NKern::RestoreInterrupts(irq);
   774 			return KErrNone;
   775 			}
   776 		}
   777 	__KTRACE_OPT(KUSB, Kern::Printf("  client not found"));
   778 	NKern::RestoreInterrupts(irq);
   779 	return KErrNotFound;
   780 	}
   781 
   782 
   783 /** Registers a notification callback for changes of the state of endpoints.
   784 
   785 	In the event of a state change of an endpoint that is spart of an interface which is owned by the LDD
   786 	specified in the callback structure, the callback's state member gets updated (using SetState) with a new
   787 	value, and the callback is executed (DoCallback). 'Endpoint state' here refers to the state of the
   788 	ENDPOINT_HALT feature of an endpoint as described in chapter 9 of the USB specification. The contents of
   789 	the state variable reflects the state of the halt features for all endpoints of the current interface
   790 	setting: bit 0 represents endpoint 1, bit 1 endpoint 2, etc. A set bit means 'endpoint halted', a cleared
   791 	bit 'endpoint not halted'.
   792 
   793 	@param aCallback A reference to a properly filled in endpoint status callback structure.
   794 
   795 	@return KErrNone if callback successfully registered, KErrGeneral if this callback is already registered
   796 	(it won't be registered twice).
   797 */
   798 EXPORT_C TInt DUsbClientController::RegisterForEndpointStatusChange(TUsbcEndpointStatusCallback& aCallback)
   799 	{
   800 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForEndpointStatusChange()"));
   801 	if (iEpStatusCallbacks.Elements() == KUsbcMaxListLength)
   802 		{
   803 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
   804 										  KUsbcMaxListLength));
   805 		return KErrGeneral;
   806 		}
   807 	if (IsInTheEpStatusList(aCallback))
   808 		{
   809 		__KTRACE_OPT(KUSB, Kern::Printf("  Error: EpStatusCallback @ 0x%x already registered", &aCallback));
   810 		return KErrGeneral;
   811 		}
   812 	const TInt irq = NKern::DisableAllInterrupts();
   813 	iEpStatusCallbacks.AddLast(aCallback);
   814 	NKern::RestoreInterrupts(irq);
   815 	return KErrNone;
   816 	}
   817 
   818 
   819 /** De-registers (removes from the list of pending requests) a notification callback for changes of the state
   820 	of endpoints.
   821 
   822 	@param aClientId A pointer to the LDD owning the endpoint status change callback.
   823 
   824 	@return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
   825 */
   826 EXPORT_C TInt DUsbClientController::DeRegisterForEndpointStatusChange(const DBase* aClientId)
   827 	{
   828 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForEndpointStatusChange()"));
   829 	__ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
   830 	const TInt irq = NKern::DisableAllInterrupts();
   831 	TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks);
   832 	TUsbcEndpointStatusCallback* p;
   833 	while ((p = iter++) != NULL)
   834 		{
   835 		if (p->Owner() == aClientId)
   836 			{
   837 			__KTRACE_OPT(KUSB, Kern::Printf("  removing EpStatusCallback @ 0x%x", p));
   838 			iEpStatusCallbacks.Remove(*p);
   839 			NKern::RestoreInterrupts(irq);
   840 			return KErrNone;
   841 			}
   842 		}
   843 	__KTRACE_OPT(KUSB, Kern::Printf("  client not found"));
   844 	NKern::RestoreInterrupts(irq);
   845 	return KErrNotFound;
   846 	}
   847 
   848 
   849 /** Returns the number of the currently active alternate interface setting for this interface.
   850 
   851 	@param aClientId A pointer to the LDD owning the interface.
   852 	@param aInterfaceNum Here the interface gets written to.
   853 
   854 	@return KErrNotFound if an interface for this client couldn't be found, KErrNone if setting value was
   855 	successfully written.
   856 */
   857 EXPORT_C TInt DUsbClientController::GetInterfaceNumber(const DBase* aClientId, TInt& aInterfaceNum) const
   858 	{
   859 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceNumber()"));
   860 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
   861 	if (ifcset < 0)
   862 		{
   863 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error (ifc < 0)"));
   864 		return KErrNotFound;
   865 		}
   866 	const TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
   867 	if (!ifcset_ptr)
   868 		{
   869 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number %d doesn't exist", ifcset));
   870 		return KErrNotFound;
   871 		}
   872 	aInterfaceNum = ifcset_ptr->iCurrentInterface;
   873 	return KErrNone;
   874 	}
   875 
   876 
   877 /** This is normally called once by an LDD's destructor, either after a Close() on the user side,
   878 	or during general cleanup.
   879 
   880 	It might also be called by the LDD when some internal unrecoverable error occurs.
   881 
   882 	This function
   883 	- de-registers a possibly pending device state change notification request,
   884 	- de-registers a possibly pending endpoint state change notification request,
   885 	- releases all interfaces + settings owned by this LDD,
   886 	- cancels all remaining (if any) read/write requests.
   887 
   888 	@param aClientId A pointer to the LDD to be unregistered.
   889 
   890 	@return KErrNone.
   891 */
   892 EXPORT_C TInt DUsbClientController::DeRegisterClient(const DBase* aClientId)
   893 	{
   894 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClient(0x%x)", aClientId));
   895 	// Cancel all device state notification requests
   896 	DeRegisterForStatusChange(aClientId);
   897 	// Cancel all endpoint state notification requests
   898 	DeRegisterForEndpointStatusChange(aClientId);
   899 	DeRegisterForOtgFeatureChange(aClientId);
   900 	DeRegisterClientCallback(aClientId);
   901 	// Delete the interface including all its alternate settings which might exist.
   902 	// (If we release the default setting (0), all alternate settings are deleted as well.)
   903 	const TInt r = ReleaseInterface(aClientId, 0);
   904 	// Cancel all remaining (if any) read/write requests
   905 	DeleteRequestCallbacks(aClientId);
   906 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClient: Done."));
   907 	return r;
   908 	}
   909 
   910 
   911 /** Returns the currently used Ep0 max packet size.
   912 
   913 	@return The currently used Ep0 max packet size.
   914 */
   915 EXPORT_C TInt DUsbClientController::Ep0PacketSize() const
   916 	{
   917 	const TUsbcLogicalEndpoint* const ep = iRealEndpoints[0].iLEndpoint;
   918 	if (iHighSpeed)
   919 		{
   920 		__KTRACE_OPT(KUSB, Kern::Printf("  Ep0 size = %d (HS)", ep->iEpSize_Hs));
   921 		return ep->iEpSize_Hs;
   922 		}
   923 	else
   924 		{
   925 		__KTRACE_OPT(KUSB, Kern::Printf("  Ep0 size = %d (FS)", ep->iEpSize_Fs));
   926 		return ep->iEpSize_Fs;
   927 		}
   928 	}
   929 
   930 
   931 /** Stalls Ep0.
   932 
   933 	@param aClientId A pointer to the LDD wishing to stall Ep0 (this is for PIL internal purposes only).
   934 
   935 	@return KErrNone if endpoint zero successfully stalled, KErrGeneral otherwise.
   936 */
   937 EXPORT_C TInt DUsbClientController::Ep0Stall(const DBase* aClientId)
   938 	{
   939 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Ep0Stall()"));
   940 	if (aClientId == iEp0ClientId)
   941 		{
   942 		ResetEp0DataOutVars();
   943 		}
   944 	const TInt err = StallEndpoint(KEp0_Out);
   945 	if (err < 0)
   946 		{
   947 		return err;
   948 		}
   949 	else
   950 		return StallEndpoint(KEp0_In);
   951 	}
   952 
   953 
   954 /** Sends a zero-byte status packet on Ep0.
   955 
   956 	@param aClientId A pointer to the LDD wishing to send the status packet (not used at present).
   957 */
   958 EXPORT_C void DUsbClientController::SendEp0StatusPacket(const DBase* /* aClientId */)
   959 	{
   960 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SendEp0StatusPacket()"));
   961 	SendEp0ZeroByteStatusPacket();
   962 	}
   963 
   964 
   965 /** Returns the current USB device state.
   966 
   967 	'USB device state' here refers to the Visible Device States as defined in chapter 9 of the USB
   968 	specification.
   969 
   970 	@return The current USB device state, or EUsbcDeviceStateUndefined if the UDC doesn't allow device state
   971 	tracking (PSL's DeviceStateChangeCaps() returns EFalse).
   972 */
   973 EXPORT_C TUsbcDeviceState DUsbClientController::GetDeviceStatus() const
   974 	{
   975 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceStatus()"));
   976 	return iDeviceState;
   977 	}
   978 
   979 
   980 /** Returns the state of an endpoint.
   981 
   982 	'Endpoint state' here refers to the state of the ENDPOINT_HALT feature of
   983 	an endpoint as described in chapter 9 of the USB specification.
   984 
   985 	@param aClientId A pointer to the LDD owning the interface which contains the endpoint to be queried.
   986 	@param aEndpointNum The number of the endpoint to be queried.
   987 
   988 	@return The current endpoint state, or EEndpointStateUnknown if the endpoint couldn't be found.
   989 */
   990 EXPORT_C TEndpointState DUsbClientController::GetEndpointStatus(const DBase* aClientId, TInt aEndpointNum) const
   991 	{
   992 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetEndpointStatus()"));
   993 	return EndpointStallStatus(aEndpointNum) ?
   994 		EEndpointStateStalled :
   995 		EEndpointStateNotStalled;
   996 	}
   997 
   998 
   999 /** Sets up a data read request for an endpoint.
  1000 
  1001 	@param aCallback A reference to a properly filled in data transfer request callback structure.
  1002 
  1003 	@return KErrNone if callback successfully registered or if this callback is already registered
  1004 	(but it won't be registered twice), KErrNotFound if the endpoint couldn't be found, KErrArgument if
  1005 	endpoint number invalid (PSL), KErrGeneral if something else goes wrong.
  1006 */
  1007 EXPORT_C TInt DUsbClientController::SetupReadBuffer(TUsbcRequestCallback& aCallback)
  1008 	{
  1009 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupReadBuffer()"));
  1010 	const TInt ep = aCallback.iRealEpNum;
  1011 	__KTRACE_OPT(KUSB, Kern::Printf("  logical ep: #%d", aCallback.iEndpointNum));
  1012 	__KTRACE_OPT(KUSB, Kern::Printf("  real ep:    #%d", ep));
  1013 	TInt err = KErrGeneral;
  1014 	if (ep != 0)
  1015 		{
  1016 		if (iRequestCallbacks[ep])
  1017 			{
  1018 			__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: RequestCallback already registered for that ep"));
  1019 			if (iRequestCallbacks[ep] == &aCallback)
  1020 				{
  1021 				__KTRACE_OPT(KPANIC, Kern::Printf("  (this same RequestCallback @ 0x%x)", &aCallback));
  1022 				}
  1023 			else
  1024 				{
  1025 				__KTRACE_OPT(KPANIC, Kern::Printf("  (a different RequestCallback @ 0x%x)", &aCallback));
  1026 				}
  1027 			return KErrNone;
  1028 			}
  1029 		// This may seem awkward:
  1030 		// First we add a callback, and then, in case of an error, we remove it again.
  1031 		// However this is necessary because the transfer request might complete (through
  1032 		// an ISR) _before_ the SetupEndpointRead function returns. Since we don't know the
  1033 		// outcome, we have to provide the callback before making the setup call.
  1034 		//
  1035 		__KTRACE_OPT(KUSB, Kern::Printf("  adding RequestCallback[%d] @ 0x%x", ep, &aCallback));
  1036 		iRequestCallbacks[ep] = &aCallback;
  1037 		if ((err = SetupEndpointRead(ep, aCallback)) != KErrNone)
  1038 			{
  1039 			__KTRACE_OPT(KPANIC, Kern::Printf("  removing RequestCallback @ 0x%x (due to error)",
  1040 											  &aCallback));
  1041 			iRequestCallbacks[ep] = NULL;
  1042 			}
  1043 		}
  1044 	else													// (ep == 0)
  1045 		{
  1046 		if (iEp0ReadRequestCallbacks.Elements() == KUsbcMaxListLength)
  1047 			{
  1048 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
  1049 											  KUsbcMaxListLength));
  1050 			return KErrGeneral;
  1051 			}
  1052 		if (IsInTheRequestList(aCallback))
  1053 			{
  1054 			__KTRACE_OPT(KUSB, Kern::Printf("  RequestCallback @ 0x%x already registered", &aCallback));
  1055 			return KErrNone;
  1056 			}
  1057 		// Ep0 reads don't need to be prepared - there's always one pending
  1058 		__KTRACE_OPT(KUSB, Kern::Printf("  adding RequestCallback @ 0x%x (ep0)", &aCallback));
  1059 		TInt irq = NKern::DisableAllInterrupts();
  1060 		iEp0ReadRequestCallbacks.AddLast(aCallback);
  1061 		NKern::RestoreInterrupts(irq);
  1062 		err = KErrNone;
  1063 		if (iEp0_RxExtraData)
  1064 			{
  1065 			__KTRACE_OPT(KUSB, Kern::Printf("  iEp0_RxExtraData: trying again..."));
  1066 			const TBool rx_data = iEp0DataReceiving;
  1067 			const TInt irq = NKern::DisableAllInterrupts();
  1068 			err = ProcessEp0ReceiveDone(iEp0_RxExtraCount);
  1069 			NKern::RestoreInterrupts(irq);
  1070 			if (err == KErrNone)
  1071 				{
  1072 				iEp0_RxExtraData = EFalse;
  1073 				// Queue a new Ep0 read (because xxxProceed only re-enables the interrupt)
  1074 				SetupEndpointZeroRead();
  1075 				if (rx_data)
  1076 					{
  1077 					Ep0ReceiveProceed();
  1078 					}
  1079 				else
  1080 					{
  1081 					Ep0ReadSetupPktProceed();
  1082 					}
  1083 				__KTRACE_OPT(KUSB, Kern::Printf("  :-)"));
  1084 				}
  1085 			else
  1086 				{
  1087 				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: :-("));
  1088 				err = KErrGeneral;
  1089 				}
  1090 			return err;
  1091 			}
  1092 		}
  1093 	return err;
  1094 	}
  1095 
  1096 
  1097 /** Sets up a data write request for an endpoint.
  1098 
  1099 	@param aCallback A reference to a properly filled in data transfer request callback structure.
  1100 
  1101 	@return KErrNone if callback successfully registered or if this callback is already registered
  1102 	(but it won't be registered twice), KErrNotFound if the endpoint couldn't be found, KErrArgument if
  1103 	endpoint number invalid (PSL), KErrGeneral if something else goes wrong.
  1104 */
  1105 EXPORT_C TInt DUsbClientController::SetupWriteBuffer(TUsbcRequestCallback& aCallback)
  1106 	{
  1107 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupWriteBuffer()"));
  1108 	TInt ep = aCallback.iRealEpNum;
  1109 	__KTRACE_OPT(KUSB, Kern::Printf("  logical ep: #%d", aCallback.iEndpointNum));
  1110 	__KTRACE_OPT(KUSB, Kern::Printf("  real ep:	   #%d", ep));
  1111 	if (iRequestCallbacks[ep])
  1112 		{
  1113 		__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: RequestCallback already registered for that ep"));
  1114 		if (iRequestCallbacks[ep] == &aCallback)
  1115 			{
  1116 			__KTRACE_OPT(KPANIC, Kern::Printf("  (this same RequestCallback @ 0x%x)", &aCallback));
  1117 			return KErrNone;
  1118 			}
  1119 		else
  1120 			{
  1121 			__KTRACE_OPT(KPANIC, Kern::Printf("  (a different RequestCallback @ 0x%x - poss. error)",
  1122 											  &aCallback));
  1123 			return KErrGeneral;
  1124 			}
  1125 		}
  1126 	if (ep == 0)
  1127 		{
  1128 		if (iEp0_TxNonStdCount)
  1129 			{
  1130 			if (iEp0_TxNonStdCount > aCallback.iLength)
  1131 				{
  1132 				__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Ep0 is sending less data than requested"));
  1133 				if ((aCallback.iLength % iEp0MaxPacketSize == 0) && !aCallback.iZlpReqd)
  1134 					{
  1135 					__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Zlp should probably be requested"));
  1136 					}
  1137 				}
  1138 			else if (iEp0_TxNonStdCount < aCallback.iLength)
  1139 				{
  1140 				__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Ep0 is sending more data than requested"));
  1141 				}
  1142 			iEp0_TxNonStdCount = 0;
  1143 			}
  1144 		// Ep0 IN needs to be adjusted: the LDD uses 0 for both Ep0 directions.
  1145 		ep = KEp0_Tx;
  1146 		}
  1147 	// This may seem awkward:
  1148 	// First we add a callback, and then, in case of an error, we remove it again.
  1149 	// However this is necessary because the transfer request might complete (through
  1150 	// an ISR) _before_ the SetupEndpointWrite function returns. Since we don't know the
  1151 	// outcome, we have to provide the callback before making the setup call.
  1152 	//
  1153 	__KTRACE_OPT(KUSB, Kern::Printf("  adding RequestCallback[%d] @ 0x%x", ep, &aCallback));
  1154 	iRequestCallbacks[ep] = &aCallback;
  1155 	if (ep == KEp0_Tx)
  1156 		{
  1157 		iEp0ClientDataTransmitting = ETrue;			 // this must be set before calling SetupEndpointZeroWrite
  1158 		if (SetupEndpointZeroWrite(aCallback.iBufferStart, aCallback.iLength, aCallback.iZlpReqd) != KErrNone)
  1159 			{
  1160 			__KTRACE_OPT(KPANIC, Kern::Printf("  removing RequestCallback @ 0x%x (due to error)", &aCallback));
  1161 			iRequestCallbacks[ep] = NULL;
  1162 			iEp0ClientDataTransmitting = EFalse;
  1163 			}
  1164 		}
  1165 	else if (SetupEndpointWrite(ep, aCallback) != KErrNone)
  1166 		{
  1167 		__KTRACE_OPT(KPANIC, Kern::Printf("  removing RequestCallback @ 0x%x (due to error)", &aCallback));
  1168 		iRequestCallbacks[ep] = NULL;
  1169 		}
  1170 	return KErrNone;
  1171 	}
  1172 
  1173 
  1174 /** Cancels a data read request for an endpoint.
  1175 
  1176 	The request callback will be removed from the queue and the
  1177 	callback function won't be executed.
  1178 
  1179 	@param aClientId A pointer to the LDD owning the interface which contains the endpoint.
  1180 	@param aRealEndpoint The number of the endpoint for which the transfer request is to be cancelled.
  1181 */
  1182 EXPORT_C void DUsbClientController::CancelReadBuffer(const DBase* aClientId, TInt aRealEndpoint)
  1183 	{
  1184 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelReadBuffer(%d)", aRealEndpoint));
  1185 	if (aRealEndpoint < 0)
  1186 		{
  1187 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: ep # < 0: %d", aRealEndpoint));
  1188 		return;
  1189 		}
  1190 	// Note that we here don't cancel Ep0 read requests at the PSL level!
  1191 	if (aRealEndpoint > 0)
  1192 		{
  1193 		CancelEndpointRead(aRealEndpoint);
  1194 		}
  1195 	DeleteRequestCallback(aClientId, aRealEndpoint, EControllerRead);
  1196 	}
  1197 
  1198 
  1199 /** Cancels a data write request for an endpoint.
  1200 
  1201 	It cannot be guaranteed that the data is not sent nonetheless, as some UDCs don't permit a flushing of a
  1202 	TX FIFO once it has been filled. The request callback will be removed from the queue in any case and the
  1203 	callback function won't be executed.
  1204 
  1205 	@param aClientId A pointer to the LDD owning the interface which contains the endpoint.
  1206 	@param aRealEndpoint The number of the endpoint for which the transfer request is to be cancelled.
  1207 */
  1208 EXPORT_C void DUsbClientController::CancelWriteBuffer(const DBase* aClientId, TInt aRealEndpoint)
  1209 	{
  1210 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelWriteBuffer(%d)", aRealEndpoint));
  1211 	if (aRealEndpoint < 0)
  1212 		{
  1213 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: ep # < 0: %d", aRealEndpoint));
  1214 		return;
  1215 		}
  1216 	if (aRealEndpoint == 0)
  1217 		{
  1218 		// Ep0 IN needs to be adjusted: the LDD uses 0 for both Ep0 directions.
  1219 		aRealEndpoint = KEp0_Tx;
  1220 		}
  1221 	CancelEndpointWrite(aRealEndpoint);
  1222 	if (aRealEndpoint == KEp0_Tx)
  1223 		{
  1224 		// Since Ep0 is shared among clients, we don't have to care about the client id.
  1225 		iEp0WritePending = EFalse;
  1226 		}
  1227 	DeleteRequestCallback(aClientId, aRealEndpoint, EControllerWrite);
  1228 	}
  1229 
  1230 
  1231 /** Halts (stalls) an endpoint (but not Ep0).
  1232 
  1233 	@param aClientId A pointer to the LDD owning the interface which contains the endpoint to be stalled.
  1234 	@param aEndpointNum The number of the endpoint.
  1235 
  1236 	@return KErrNotFound if endpoint couldn't be found (includes Ep0), KErrNone if endpoint successfully
  1237 	stalled, KErrGeneral otherwise.
  1238 */
  1239 EXPORT_C TInt DUsbClientController::HaltEndpoint(const DBase* aClientId, TInt aEndpointNum)
  1240 	{
  1241 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::HaltEndpoint(%d)", aEndpointNum));
  1242 	const TInt r = StallEndpoint(aEndpointNum);
  1243 	if (r == KErrNone)
  1244 		{
  1245 		iRealEndpoints[aEndpointNum].iHalt = ETrue;
  1246 		}
  1247 	else if (r == KErrArgument)
  1248 		{
  1249 		return KErrNotFound;
  1250 		}
  1251 	return r;
  1252 	}
  1253 
  1254 
  1255 /** Clears the halt condition of an endpoint (but not Ep0).
  1256 
  1257 	@param aClientId A pointer to the LDD owning the interface which contains the endpoint to be un-stalled.
  1258 	@param aEndpointNum The number of the endpoint.
  1259 
  1260 	@return KErrNotFound if endpoint couldn't be found (includes Ep0), KErrNone if endpoint successfully
  1261 	stalled, KErrGeneral otherwise.
  1262 */
  1263 EXPORT_C TInt DUsbClientController::ClearHaltEndpoint(const DBase* aClientId, TInt aEndpointNum)
  1264 	{
  1265 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ClearHaltEndpoint(%d)", aEndpointNum));
  1266 	const TInt r = ClearStallEndpoint(aEndpointNum);
  1267 	if (r == KErrNone)
  1268 		{
  1269 		iRealEndpoints[aEndpointNum].iHalt = EFalse;
  1270 		}
  1271 	else if (r == KErrArgument)
  1272 		{
  1273 		return KErrNotFound;
  1274 		}
  1275 	return r;
  1276 	}
  1277 
  1278 
  1279 /** This function requests 'device control' for an LDD.
  1280 
  1281 	Class or vendor specific Ep0 requests addressed to the USB device as a whole (Recipient field in
  1282 	bmRequestType byte of a Setup packet set to zero) are delivered to the LDD that owns device control. For
  1283 	obvious reasons only one USB LDD can have device control at any given time.
  1284 
  1285 	@param aClientId A pointer to the LDD requesting device control.
  1286 
  1287 	@return KErrNone if device control successfully claimed or if this LDD already owns it, KErrGeneral if
  1288 	device control already owned by a different client.
  1289 */
  1290 EXPORT_C TInt DUsbClientController::SetDeviceControl(const DBase* aClientId)
  1291 	{
  1292 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceControl()"));
  1293 	if (iEp0DeviceControl)
  1294 		{
  1295 		if (iEp0DeviceControl == aClientId)
  1296 			{
  1297 			__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Device Control already owned by this client"));
  1298 			return KErrNone;
  1299 			}
  1300 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device Control already claimed by a different client"));
  1301 		return KErrGeneral;
  1302 		}
  1303 	iEp0DeviceControl = aClientId;
  1304 	return KErrNone;
  1305 	}
  1306 
  1307 
  1308 /** This function releases device control for an LDD.
  1309 
  1310 	@see DUsbClientController::SetDeviceControl()
  1311 
  1312 	@param aClientId A pointer to the LDD releasing device control.
  1313 
  1314 	@return KErrNone if device control successfully released, KErrGeneral if device control owned by a
  1315 	different client or by no client at all.
  1316 */
  1317 EXPORT_C TInt DUsbClientController::ReleaseDeviceControl(const DBase* aClientId)
  1318 	{
  1319 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReleaseDeviceControl()"));
  1320 	if (iEp0DeviceControl)
  1321 		{
  1322 		if (iEp0DeviceControl == aClientId)
  1323 			{
  1324 			__KTRACE_OPT(KUSB, Kern::Printf("  Releasing Device Control"));
  1325 			iEp0DeviceControl = NULL;
  1326 			return KErrNone;
  1327 			}
  1328 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device Control owned by a different client"));
  1329 		}
  1330 	else
  1331 		{
  1332 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device Control not owned by any client"));
  1333 		}
  1334 	return KErrGeneral;
  1335 	}
  1336 
  1337 
  1338 /** Returns all available (configurable) max packet sizes for Ep0.
  1339 
  1340 	The information is coded as bitwise OR'ed values of KUsbEpSizeXXX constants (the bitmap format used for
  1341 	TUsbcEndpointCaps.iSupportedSizes).
  1342 
  1343 	@return All available (configurable) max packet sizes for Ep0.
  1344 */
  1345 EXPORT_C TUint DUsbClientController::EndpointZeroMaxPacketSizes() const
  1346 	{
  1347 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointZeroMaxPacketSizes()"));
  1348 	return iRealEndpoints[0].iCaps.iSizes;
  1349 	}
  1350 
  1351 
  1352 /** Sets (configures) the max packet size for Ep0.
  1353 
  1354 	For available sizes as returned by DUsbClientController::EndpointZeroMaxPacketSizes()
  1355 
  1356 	Note that for HS operation the Ep0 size cannot be chosen, but is fixed at 64 bytes.
  1357 
  1358 	@return KErrNotSupported if invalid size specified, KErrNone if new max packet size successfully set or
  1359 	requested size was already set.
  1360 */
  1361 EXPORT_C TInt DUsbClientController::SetEndpointZeroMaxPacketSize(TInt aMaxPacketSize)
  1362 	{
  1363 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetEndpointZeroMaxPacketSize(%d)",
  1364 									aMaxPacketSize));
  1365 
  1366 	if (DeviceHighSpeedCaps())
  1367 		{
  1368 		// We're not going to mess with this on a HS device.
  1369 		return KErrNone;
  1370 		}
  1371 
  1372 	if (!(iRealEndpoints[0].iCaps.iSizes & PacketSize2Mask(aMaxPacketSize)))
  1373 		{
  1374 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid size"));
  1375 		return KErrNotSupported;
  1376 		}
  1377 	if (iRealEndpoints[0].iLEndpoint->iEpSize_Fs == aMaxPacketSize)
  1378 		{
  1379 		__KTRACE_OPT(KUSB, Kern::Printf("  this packet size already set -> returning"));
  1380 		return KErrNone;
  1381 		}
  1382 	const TUsbcLogicalEndpoint* const ep0_0 = iRealEndpoints[0].iLEndpoint;
  1383 	const TUsbcLogicalEndpoint* const ep0_1 = iRealEndpoints[1].iLEndpoint;
  1384 	const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iEpSize_Fs = aMaxPacketSize;
  1385 	const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iEpSize_Fs = aMaxPacketSize;
  1386 
  1387 	// @@@ We should probably modify the device descriptor here as well...
  1388 
  1389 	if (iHardwareActivated)
  1390 		{
  1391 		// De-configure endpoint zero
  1392 		DeConfigureEndpoint(KEp0_Out);
  1393 		DeConfigureEndpoint(KEp0_In);
  1394 		// Re-configure endpoint zero
  1395 		const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Fs;
  1396 		const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Fs;
  1397 		ConfigureEndpoint(0, ep0_0->iInfo);
  1398 		ConfigureEndpoint(1, ep0_1->iInfo);
  1399 		iEp0MaxPacketSize = ep0_0->iInfo.iSize;
  1400 		}
  1401 	return KErrNone;
  1402 	}
  1403 
  1404 
  1405 /** Returns the current USB Device descriptor.
  1406 
  1407 	@param aThread A pointer to the thread the LDD requesting the descriptor is running in.
  1408 	@param aDeviceDescriptor A reference to a buffer into which the requested descriptor should be written
  1409 	(most likely located user-side).
  1410 
  1411 	@return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
  1412 	buffer.
  1413 */
  1414 EXPORT_C TInt DUsbClientController::GetDeviceDescriptor(DThread* aThread, TDes8& aDeviceDescriptor)
  1415 	{
  1416 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceDescriptor()"));
  1417 	return iDescriptors.GetDeviceDescriptorTC(aThread, aDeviceDescriptor);
  1418 	}
  1419 
  1420 
  1421 /** Sets a new USB Device descriptor.
  1422 
  1423 	@param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
  1424 	@param aDeviceDescriptor A reference to a buffer which contains the descriptor to be set (most likely
  1425 	located user-side).
  1426 
  1427 	@return The return value of the thread read operation, Kern::ThreadRead(), when reading from the source
  1428 	buffer in case of a failure, KErrNone if the new descriptor was successfully set.
  1429 */
  1430 EXPORT_C TInt DUsbClientController::SetDeviceDescriptor(DThread* aThread, const TDes8& aDeviceDescriptor)
  1431 	{
  1432 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceDescriptor()"));
  1433 	return iDescriptors.SetDeviceDescriptorTC(aThread, aDeviceDescriptor);
  1434 	}
  1435 
  1436 
  1437 /** Returns the current USB Device descriptor size.
  1438 
  1439 	@param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
  1440 	@param aSize A reference to a buffer into which the requested descriptor size should be written
  1441 	(most likely located user-side).
  1442 
  1443 	@return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
  1444 	buffer.
  1445 */
  1446 EXPORT_C TInt DUsbClientController::GetDeviceDescriptorSize(DThread* aThread, TDes8& aSize)
  1447 	{
  1448 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceDescriptorSize()"));
  1449 	// We do not really enquire here....
  1450 	const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Device), sizeof(KUsbDescSize_Device));
  1451 	return Kern::ThreadDesWrite(aThread, &aSize, size, 0);
  1452 	}
  1453 
  1454 
  1455 /** Returns the current USB configuration descriptor.
  1456 
  1457 	@param aThread A pointer to the thread the LDD requesting the descriptor is running in.
  1458 	@param aConfigurationDescriptor A reference to a buffer into which the requested descriptor should be
  1459 	written (most likely located user-side).
  1460 
  1461 	@return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
  1462 	buffer.
  1463 */
  1464 EXPORT_C TInt DUsbClientController::GetConfigurationDescriptor(DThread* aThread, TDes8& aConfigurationDescriptor)
  1465 	{
  1466 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationDescriptor()"));
  1467 	return iDescriptors.GetConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
  1468 	}
  1469 
  1470 
  1471 /** Sets a new USB configuration descriptor.
  1472 
  1473 	@param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
  1474 	@param aConfigurationDescriptor A reference to a buffer which contains the descriptor to be set (most
  1475 	likely located user-side).
  1476 
  1477 	@return The return value of the thread read operation, Kern::ThreadRead() when reading from the source
  1478 	buffer in case of a failure, KErrNone if the new descriptor was successfully set.
  1479 */
  1480 EXPORT_C TInt DUsbClientController::SetConfigurationDescriptor(DThread* aThread,
  1481 															   const TDes8& aConfigurationDescriptor)
  1482 	{
  1483 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetConfigurationDescriptor()"));
  1484 	return iDescriptors.SetConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
  1485 	}
  1486 
  1487 
  1488 /** Returns the current USB configuration descriptor size.
  1489 
  1490 	@param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
  1491 	@param aSize A reference to a buffer into which the requested descriptor size should be written
  1492 	(most likely located user-side).
  1493 
  1494 	@return The return value of the thread write operation, Kern::ThreadWrite(), when writing to the target
  1495 	buffer.
  1496 */
  1497 EXPORT_C TInt DUsbClientController::GetConfigurationDescriptorSize(DThread* aThread, TDes8& aSize)
  1498 	{
  1499 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationDescriptorSize()"));
  1500 	// We do not really enquire here....
  1501 	const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Config), sizeof(KUsbDescSize_Config));
  1502 	return Kern::ThreadDesWrite(aThread, &aSize, size, 0);
  1503 	}
  1504 
  1505 
  1506 /** Returns the current USB OTG descriptor.
  1507 
  1508 	@param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
  1509 	@param aOtgDesc A reference to a buffer into which the requested descriptor should be
  1510 	written (most likely located user-side).
  1511 
  1512 	@return KErrNotSupported or the return value of the thread write operation, Kern::ThreadDesWrite(),
  1513 	when writing to the target buffer.
  1514 */
  1515 EXPORT_C TInt DUsbClientController::GetOtgDescriptor(DThread* aThread, TDes8& aOtgDesc) const
  1516 	{
  1517 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtgDescriptor()"));
  1518 	if (!iOtgSupport)
  1519 		{
  1520 		return KErrNotSupported;
  1521 		}
  1522 	return iDescriptors.GetOtgDescriptorTC(aThread, aOtgDesc);
  1523 	}
  1524 
  1525 
  1526 /** Sets a new OTG descriptor.
  1527 
  1528 	@param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
  1529 	@param aOtgDesc A reference to a buffer which contains new OTG descriptor.
  1530 
  1531 	@return KErrNotSupported or the return value of the thread read operation, Kern::ThreadDesRead().
  1532 */
  1533 EXPORT_C TInt DUsbClientController::SetOtgDescriptor(DThread* aThread, const TDesC8& aOtgDesc)
  1534 	{
  1535 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetOtgDescriptor()"));
  1536 	if (!iOtgSupport)
  1537 		{
  1538 		return KErrNotSupported;
  1539 		}
  1540 	TBuf8<KUsbDescSize_Otg> otg;
  1541 	const TInt r = Kern::ThreadDesRead(aThread, &aOtgDesc, otg, 0);
  1542 	if (r != KErrNone)
  1543 		{
  1544 		return r;
  1545 		}
  1546 	// Check descriptor validity
  1547 	if (otg[0] != KUsbDescSize_Otg || otg[1] != KUsbDescType_Otg || otg[2] > 3)
  1548 		{
  1549 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid OTG descriptor"));
  1550 		return KErrGeneral;
  1551 		}
  1552 	__KTRACE_OPT(KUSB, Kern::Printf("  iOtgFuncMap before: 0x%x", iOtgFuncMap));
  1553 	// Update value in controller as well
  1554 	const TUint8 hnp = otg[2] & KUsbOtgAttr_HnpSupp;
  1555 	const TUint8 srp = otg[2] & KUsbOtgAttr_SrpSupp;
  1556 	if (hnp && !srp)
  1557 		{
  1558 		__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Invalid OTG attribute combination (HNP && !SRP"));
  1559 		}
  1560 	if (hnp && !(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
  1561 		{
  1562 		__KTRACE_OPT(KUSB, Kern::Printf("  Setting attribute KUsbOtgAttr_HnpSupp"));
  1563 		iOtgFuncMap |= KUsbOtgAttr_HnpSupp;
  1564 		}
  1565 	else if (!hnp && (iOtgFuncMap & KUsbOtgAttr_HnpSupp))
  1566 		{
  1567 		__KTRACE_OPT(KUSB, Kern::Printf("  Removing attribute KUsbOtgAttr_HnpSupp"));
  1568 		iOtgFuncMap &= ~KUsbOtgAttr_HnpSupp;
  1569 		}
  1570 	if (srp && !(iOtgFuncMap & KUsbOtgAttr_SrpSupp))
  1571 		{
  1572 		__KTRACE_OPT(KUSB, Kern::Printf("  Setting attribute KUsbOtgAttr_SrpSupp"));
  1573 		iOtgFuncMap |= KUsbOtgAttr_SrpSupp;
  1574 		}
  1575 	else if (!srp && (iOtgFuncMap & KUsbOtgAttr_SrpSupp))
  1576 		{
  1577 		__KTRACE_OPT(KUSB, Kern::Printf("  Removing attribute KUsbOtgAttr_SrpSupp"));
  1578 		iOtgFuncMap &= ~KUsbOtgAttr_SrpSupp;
  1579 		}
  1580 	__KTRACE_OPT(KUSB, Kern::Printf("  iOtgFuncMap after:  0x%x", iOtgFuncMap));
  1581 	return iDescriptors.SetOtgDescriptor(otg);
  1582 	}
  1583 
  1584 
  1585 /** Returns current OTG features of USB device.
  1586 
  1587 	@param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
  1588 	@param aFeatures A reference to a buffer into which the requested OTG features should be written.
  1589 
  1590 	@return KErrNotSupported or the return value of the thread write operation, Kern::ThreadDesWrite().
  1591 */
  1592 EXPORT_C TInt DUsbClientController::GetOtgFeatures(DThread* aThread, TDes8& aFeatures) const
  1593 	{
  1594 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtgFeatures()"));
  1595 	if (!iOtgSupport)
  1596 		{
  1597 		return KErrNotSupported;
  1598 		}
  1599 	TBuf8<1> features(1);
  1600 	features[0] = iOtgFuncMap & 0x1C;
  1601 	return Kern::ThreadDesWrite(aThread, &aFeatures, features, 0);
  1602     }
  1603 
  1604 
  1605 /** Returns current OTG features of USB device. This function is intended to be
  1606 	called only from kernel side.
  1607 
  1608 	@param aFeatures The reference to which the current features should be set at.
  1609 	@return KErrNone if successful, KErrNotSupported if OTG is unavailable.
  1610 */
  1611 EXPORT_C TInt DUsbClientController::GetCurrentOtgFeatures(TUint8& aFeatures) const
  1612 	{
  1613 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetCurrentOtgFeatures()"));
  1614 	if (!iOtgSupport)
  1615 		{
  1616 		return KErrNotSupported;
  1617 		}
  1618 	aFeatures = iOtgFuncMap & 0x1C;
  1619 	return KErrNone;
  1620 	}
  1621 
  1622 
  1623 /** Registers client request for OTG feature change. Client is notified when any OTG
  1624 	feature is changed.
  1625 
  1626 	@see KUsbOtgAttr_B_HnpEnable, KUsbOtgAttr_A_HnpSupport, KUsbOtgAttr_A_AltHnpSupport
  1627 
  1628 	@param aCallback Callback function. Gets called when OTG features change
  1629 
  1630 	@return KErrNone if successful, KErrAlreadyExists if aCallback is already in the queue.
  1631 */
  1632 EXPORT_C TInt DUsbClientController::RegisterForOtgFeatureChange(TUsbcOtgFeatureCallback& aCallback)
  1633 	{
  1634 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterForOtgFeatureChange()"));
  1635 	if (iOtgCallbacks.Elements() == KUsbcMaxListLength)
  1636 		{
  1637 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Maximum list length reached: %d",
  1638 										  KUsbcMaxListLength));
  1639 		return KErrGeneral;
  1640 		}
  1641 	if (IsInTheOtgFeatureList(aCallback))
  1642 		{
  1643 		__KTRACE_OPT(KUSB, Kern::Printf("  Error: OtgFeatureCallback @ 0x%x already registered", &aCallback));
  1644 		return KErrAlreadyExists;
  1645 		}
  1646 	const TInt irq = NKern::DisableAllInterrupts();
  1647 	iOtgCallbacks.AddLast(aCallback);
  1648 	NKern::RestoreInterrupts(irq);
  1649 	return KErrNone;
  1650 	}
  1651 
  1652 
  1653 /** De-registers (removes from the list of pending requests) a notification callback for
  1654 	OTG feature change.
  1655 
  1656 	@param aClientId A pointer to the LDD owning the endpoint status change callback.
  1657 
  1658 	@return KErrNone if callback successfully unregistered, KErrNotFound if the callback couldn't be found.
  1659 */
  1660 EXPORT_C TInt DUsbClientController::DeRegisterForOtgFeatureChange(const DBase* aClientId)
  1661 	{
  1662 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForOtgFeatureChange()"));
  1663 	__ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
  1664 	const TInt irq = NKern::DisableAllInterrupts();
  1665 	TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks);
  1666 	TUsbcOtgFeatureCallback* p;
  1667 	while ((p = iter++) != NULL)
  1668 		{
  1669 		if (!aClientId || p->Owner() == aClientId)
  1670 			{
  1671 			__KTRACE_OPT(KUSB, Kern::Printf("  removing OtgFeatureCallback @ 0x%x", p));
  1672 			iOtgCallbacks.Remove(*p);
  1673 			NKern::RestoreInterrupts(irq);
  1674 			return KErrNone;
  1675 			}
  1676 		}
  1677 	__KTRACE_OPT(KUSB, Kern::Printf("  client not found"));
  1678 	NKern::RestoreInterrupts(irq);
  1679 	return KErrNotFound;
  1680 	}
  1681 
  1682 
  1683 /** Returns a specific standard USB interface descriptor.
  1684 
  1685 	@param aThread A pointer to the thread the LDD requesting the descriptor is running in.
  1686 	@param aClientId A pointer to the LDD requesting the descriptor.
  1687 	@param aSettingNum The setting number of the interface for which the descriptor is requested.
  1688 	@param aInterfaceDescriptor A reference to a buffer into which the requested descriptor should be written
  1689 	(most likely located user-side).
  1690 
  1691 	@return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
  1692 	write operation, Kern::ThreadWrite(), when writing to the target buffer.
  1693 */
  1694 EXPORT_C TInt DUsbClientController::GetInterfaceDescriptor(DThread* aThread, const DBase* aClientId,
  1695 														   TInt aSettingNum, TDes8& aInterfaceDescriptor)
  1696 	{
  1697 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceDescriptor(x, 0x%08x, %d, y)",
  1698 									aClientId, aSettingNum));
  1699 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  1700 	if (ifcset < 0)
  1701 		{
  1702 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  1703 		return KErrNotFound;
  1704 		}
  1705 	return iDescriptors.GetInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum);
  1706 	}
  1707 
  1708 
  1709 /** Sets a new standard USB interface descriptor.
  1710 
  1711 	This function can also be used, by the user, and under certain conditions, to change an interface's number
  1712 	(reported as bInterfaceNumber in the descriptor). The conditions are: 1) We cannot accept a number that is
  1713 	already used by another interface, 2) We allow the interface number to be changed only when it's still the
  1714 	only setting, and 3) We allow the interface number to be changed only for the default setting (0). (All
  1715 	alternate settings created for that interface thereafter will inherit the new, changed number.)
  1716 
  1717 	@param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
  1718 	@param aClientId A pointer to the LDD requesting the setting of the descriptor.
  1719 	@param aSettingNum The setting number of the interface for which the descriptor is to be set.
  1720 	@param aInterfaceDescriptor A reference to a buffer which contains the descriptor to be set (most
  1721 	likely located user-side).
  1722 
  1723 	@return KErrNotFound if the specified interface couldn't be found, the return value of the thread read
  1724 	operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrArgument if the
  1725 	interface  number is to be changed (via bInterfaceNumber in the descriptor) and either the requested
  1726 	interface number is already used by another interface or the interface has more than one setting. KErrNone
  1727 	if the new descriptor was successfully set.
  1728 */
  1729 EXPORT_C TInt DUsbClientController::SetInterfaceDescriptor(DThread* aThread, const DBase* aClientId,
  1730 														   TInt aSettingNum, const TDes8& aInterfaceDescriptor)
  1731 	{
  1732 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetInterfaceDescriptor(x, 0x%08x, %d, y)",
  1733 									aClientId, aSettingNum));
  1734 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  1735 	if (ifcset < 0)
  1736 		{
  1737 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  1738 		return KErrNotFound;
  1739 		}
  1740 	TBuf8<KUsbDescSize_Interface> new_ifc;
  1741 	TInt r = Kern::ThreadDesRead(aThread, &aInterfaceDescriptor, new_ifc, 0);
  1742 	if (r != KErrNone)
  1743 		{
  1744 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Copying interface descriptor buffer failed (%d)", r));
  1745 		return r;
  1746 		}
  1747 	const TInt ifcset_new = new_ifc[2];
  1748 	const TBool ifc_num_changes = (ifcset != ifcset_new);
  1749 	TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
  1750 	if (!ifcset_ptr)
  1751 		{
  1752 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number %d doesn't exist", ifcset));
  1753 		return KErrNotFound;
  1754 		}
  1755 	if (ifc_num_changes)
  1756 		{
  1757 		// If the user wants to change the interface number, we need to do some sanity checks:
  1758 		if (InterfaceExists(ifcset_new))
  1759 			{
  1760 			// Obviously we cannot accept a number that is already used by another interface.
  1761 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number %d already in use", ifcset_new));
  1762 			return KErrArgument;
  1763 			}
  1764 		if (ifcset_ptr->iInterfaces.Count() > 1)
  1765 			{
  1766 			// We allow the interface number to be changed only when it's the only setting.
  1767 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface has more than one alternate setting"));
  1768 			return KErrArgument;
  1769 			}
  1770 		if (aSettingNum != 0)
  1771 			{
  1772 			// We allow the interface number to be changed only when it's the default setting.
  1773 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface number can only be changed for setting 0"));
  1774 			return KErrArgument;
  1775 			}
  1776 		}
  1777 	if ((r = iDescriptors.SetInterfaceDescriptor(new_ifc, ifcset, aSettingNum)) != KErrNone)
  1778 		{
  1779 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: iDescriptors.SetInterfaceDescriptorfailed"));
  1780 		return r;
  1781 		}
  1782 	if (ifc_num_changes)
  1783 		{
  1784 		// Alright then, let's do it...
  1785 		__KTRACE_OPT(KUSB, Kern::Printf("  about to change interface number from %d to %d",
  1786 										ifcset, ifcset_new));
  1787 		ifcset_ptr->iInterfaceNumber = ifcset_new;
  1788 		}
  1789 	return KErrNone;
  1790 	}
  1791 
  1792 
  1793 /** Returns the size of a specific standard USB interface descriptor.
  1794 
  1795 	@param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
  1796 	@param aClientId A pointer to the LDD requesting the descriptor size.
  1797 	@param aSettingNum The setting number of the interface for which the descriptor size is requested.
  1798 	@param aSize A reference to a buffer into which the requested descriptor size should be written (most
  1799 	likely located user-side).
  1800 
  1801 	@return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
  1802 	write operation, Kern::ThreadWrite(), when writing to the target buffer.
  1803 */
  1804 EXPORT_C TInt DUsbClientController::GetInterfaceDescriptorSize(DThread* aThread, const DBase* aClientId,
  1805 															   TInt /*aSettingNum*/, TDes8& aSize)
  1806 	{
  1807 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetInterfaceDescriptorSize()"));
  1808 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  1809 	if (ifcset < 0)
  1810 		{
  1811 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  1812 		return KErrNotFound;
  1813 		}
  1814 	// Actually, we do not really enquire here....
  1815 	const TPtrC8 size(reinterpret_cast<const TUint8*>(&KUsbDescSize_Interface), sizeof(KUsbDescSize_Interface));
  1816 	Kern::ThreadDesWrite(aThread, &aSize, size, 0);
  1817 	return KErrNone;
  1818 	}
  1819 
  1820 
  1821 /** Returns a specific standard USB endpoint descriptor.
  1822 
  1823 	@param aThread A pointer to the thread the LDD requesting the descriptor is running in.
  1824 	@param aClientId A pointer to the LDD requesting the descriptor.
  1825 	@param aSettingNum The setting number of the interface that contains the endpoint for which the
  1826 	descriptor is requested.
  1827 	@param aEndpointNum The endpoint for which the descriptor is requested.
  1828 	@param aEndpointDescriptor A reference to a buffer into which the requested descriptor should be written
  1829 	(most likely located user-side).
  1830 
  1831 	@return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
  1832 	of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
  1833 */
  1834 EXPORT_C TInt DUsbClientController::GetEndpointDescriptor(DThread* aThread, const DBase* aClientId,
  1835 														  TInt aSettingNum, TInt aEndpointNum,
  1836 														  TDes8& aEndpointDescriptor)
  1837 	{
  1838 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetEndpointDescriptor(x, 0x%08x, %d, %d, y)",
  1839 									aClientId, aSettingNum, aEndpointNum));
  1840 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  1841 	if (ifcset < 0)
  1842 		{
  1843 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  1844 		return KErrNotFound;
  1845 		}
  1846 	return iDescriptors.GetEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
  1847 												aSettingNum, EpIdx2Addr(aEndpointNum));
  1848 	}
  1849 
  1850 
  1851 /** Sets a new standard USB endpoint descriptor.
  1852 
  1853 	@param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
  1854 	@param aClientId A pointer to the LDD requesting the setting of the descriptor.
  1855 	@param aSettingNum The setting number of the interface that contains the endpoint for which the
  1856 	descriptor is to be set.
  1857 	@param aEndpointNum The endpoint for which the descriptor is to be set.
  1858 	@param aEndpointDescriptor A reference to a buffer which contains the descriptor to be set (most
  1859 	likely located user-side).
  1860 
  1861 	@return KErrNotFound if the specified interface or endpoint couldn't be found, the return value of the
  1862 	thread read operation, Kern::ThreadRead(), when reading from the source buffer in case of a read failure,
  1863 	KErrNone if the new descriptor was successfully set.
  1864 */
  1865 EXPORT_C TInt DUsbClientController::SetEndpointDescriptor(DThread* aThread, const DBase* aClientId,
  1866 														  TInt aSettingNum, TInt aEndpointNum,
  1867 														  const TDes8& aEndpointDescriptor)
  1868 	{
  1869 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetEndpointDescriptor(x, 0x%08x, %d, %d, y)",
  1870 									aClientId, aSettingNum, aEndpointNum));
  1871 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  1872 	if (ifcset < 0)
  1873 		{
  1874 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  1875 		return KErrNotFound;
  1876 		}
  1877 	return iDescriptors.SetEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
  1878 												aSettingNum, EpIdx2Addr(aEndpointNum));
  1879 	}
  1880 
  1881 
  1882 /** Returns the size of a specific standard USB endpoint descriptor.
  1883 
  1884 	@param aThread A pointer to the thread the LDD requesting the descriptor size is running in.
  1885 	@param aClientId A pointer to the LDD requesting the descriptor size.
  1886 	@param aSettingNum The setting number of the interface that contains the endpoint for which the
  1887 	descriptor size is requested.
  1888 	@param aEndpointNum The endpoint for which the descriptor size is requested.
  1889 	@param aEndpointDescriptor A reference to a buffer into which the requested descriptor size should be
  1890 	written (most likely located user-side).
  1891 
  1892 	@return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
  1893 	of the thread write operation, kern::ThreadWrite(), when writing to the target buffer.
  1894 */
  1895 EXPORT_C TInt DUsbClientController::GetEndpointDescriptorSize(DThread* aThread, const DBase* aClientId,
  1896 															  TInt aSettingNum, TInt aEndpointNum,
  1897 															  TDes8& aSize)
  1898 	{
  1899 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetEndpointDescriptorSize(x, 0x%08x, %d, %d, y)",
  1900 									aClientId, aSettingNum, aEndpointNum));
  1901 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  1902 	if (ifcset < 0)
  1903 		{
  1904 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  1905 		return KErrNotFound;
  1906 		}
  1907 	TInt s;
  1908 	TInt r = iDescriptors.GetEndpointDescriptorSize(ifcset, aSettingNum,
  1909 													EpIdx2Addr(aEndpointNum), s);
  1910 	if (r == KErrNone)
  1911 		{
  1912 		TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
  1913 		r = Kern::ThreadDesWrite(aThread, &aSize, size, 0);
  1914 		}
  1915 	else
  1916 		{
  1917 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: endpoint descriptor not found"));
  1918 		}
  1919 	return r;
  1920 	}
  1921 
  1922 
  1923 /** Returns the current Device_Qualifier descriptor. On a USB device which doesn't support high-speed
  1924 	operation this function will return an error. Note that the contents of the descriptor depend on
  1925 	the current device speed (full-speed or high-speed).
  1926 
  1927 	@param aThread A pointer to the thread the LDD requesting the descriptor is running in.
  1928 	@param aDeviceQualifierDescriptor A reference to a buffer into which the requested descriptor
  1929 	should be written (most likely located user-side).
  1930 
  1931 	@return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
  1932 	write operation, Kern::ThreadWrite(), when writing to the target buffer.
  1933 */
  1934 EXPORT_C TInt DUsbClientController::GetDeviceQualifierDescriptor(DThread* aThread,
  1935 																 TDes8& aDeviceQualifierDescriptor)
  1936 	{
  1937 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetDeviceQualifierDescriptor()"));
  1938 	return iDescriptors.GetDeviceQualifierDescriptorTC(aThread, aDeviceQualifierDescriptor);
  1939 	}
  1940 
  1941 
  1942 /** Sets a new Device_Qualifier descriptor. On a USB device which doesn't support high-speed
  1943 	operation this function will return an error. Note that the contents of the descriptor should take
  1944 	into account the current device speed (full-speed or high-speed) as it is dependent on it.
  1945 
  1946 	@param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
  1947 	@param aDeviceQualifierDescriptor A reference to a buffer which contains the descriptor to be set (most
  1948 	likely located user-side).
  1949 
  1950 	@return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
  1951 	read operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrNone if
  1952 	the new descriptor was successfully set.
  1953 */
  1954 EXPORT_C TInt DUsbClientController::SetDeviceQualifierDescriptor(DThread* aThread,
  1955 																 const TDes8& aDeviceQualifierDescriptor)
  1956 	{
  1957 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetDeviceQualifierDescriptor()"));
  1958 	return iDescriptors.SetDeviceQualifierDescriptorTC(aThread, aDeviceQualifierDescriptor);
  1959 	}
  1960 
  1961 
  1962 /** Returns the current Other_Speed_Configuration descriptor. On a USB device which doesn't support high-speed
  1963 	operation this function will return an error. Note that the contents of the descriptor depend on the
  1964 	current device speed (full-speed or high-speed).
  1965 
  1966 	@param aThread A pointer to the thread the LDD requesting the descriptor is running in.
  1967 	@param aConfigurationDescriptor A reference to a buffer into which the requested descriptor
  1968 	should be written (most likely located user-side).
  1969 
  1970 	@return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
  1971 	write operation, Kern::ThreadWrite(), when writing to the target buffer.
  1972 */
  1973 EXPORT_C TInt DUsbClientController::GetOtherSpeedConfigurationDescriptor(DThread* aThread,
  1974 																		 TDes8& aConfigurationDescriptor)
  1975 	{
  1976 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetOtherSpeedConfigurationDescriptor()"));
  1977 	return iDescriptors.GetOtherSpeedConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
  1978 	}
  1979 
  1980 
  1981 /** Sets a new Other_Speed_Configuration descriptor. On a USB device which doesn't support high-speed
  1982 	operation this function will return an error. Note that the contents of the descriptor should take
  1983 	into account the current device speed (full-speed or high-speed) as it is dependent on it.
  1984 
  1985 	@param aThread A pointer to the thread the LDD requesting the setting of the descriptor is running in.
  1986 	@param aConfigurationDescriptor A reference to a buffer which contains the descriptor to be set (most
  1987 	likely located user-side).
  1988 
  1989 	@return KErrNotSupported if this descriptor is not supported, otherwise the return value of the thread
  1990 	read operation, Kern::ThreadRead(), when reading from the source buffer in case of a failure, KErrNone if
  1991 	the new descriptor was successfully set.
  1992 */
  1993 EXPORT_C TInt DUsbClientController::SetOtherSpeedConfigurationDescriptor(DThread* aThread,
  1994 																		 const TDes8& aConfigurationDescriptor)
  1995 	{
  1996 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetOtherSpeedConfigurationDescriptor()"));
  1997 	return iDescriptors.SetOtherSpeedConfigurationDescriptorTC(aThread, aConfigurationDescriptor);
  1998 	}
  1999 
  2000 
  2001 /** Returns a block of all available non-standard (class-specific) interface descriptors for a specific
  2002 	interface.
  2003 
  2004 	@param aThread A pointer to the thread the LDD requesting the descriptor block is running in.
  2005 	@param aClientId A pointer to the LDD requesting the descriptor block.
  2006 	@param aSettingNum The setting number of the interface for which the descriptor block is requested.
  2007 	@param aInterfaceDescriptor A reference to a buffer into which the requested descriptor(s) should be
  2008 	written (most likely located user-side).
  2009 
  2010 	@return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
  2011 	write operation, Kern::ThreadWrite(), when writing to the target buffer.
  2012 */
  2013 EXPORT_C TInt DUsbClientController::GetCSInterfaceDescriptorBlock(DThread* aThread, const DBase* aClientId,
  2014 																  TInt aSettingNum,
  2015 																  TDes8& aInterfaceDescriptor)
  2016 	{
  2017 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetCSInterfaceDescriptorBlock(x, 0x%08x, %d, y)",
  2018 									aClientId, aSettingNum));
  2019 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  2020 	if (ifcset < 0)
  2021 		{
  2022 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  2023 		return KErrNotFound;
  2024 		}
  2025 	return iDescriptors.GetCSInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum);
  2026 	}
  2027 
  2028 
  2029 /** Sets a block of (i.e. one or more) non-standard (class-specific) interface descriptors for a specific
  2030 	interface.
  2031 
  2032 	@param aThread A pointer to the thread the LDD requesting the setting of the descriptor block is running
  2033 	in.
  2034 	@param aClientId A pointer to the LDD requesting the setting of the descriptor block.
  2035 	@param aSettingNum The setting number of the interface for which the setting of the descriptor block is
  2036 	requested.
  2037 	@param aInterfaceDescriptor A reference to a buffer which contains the descriptor block to be set (most
  2038 	likely located user-side).
  2039 	@param aSize The size of the descriptor block to be set.
  2040 
  2041 	@return KErrNotFound if the specified interface couldn't be found, KErrArgument if aSize is less than 2,
  2042 	KErrNoMemory if enough memory for the new descriptor(s) couldn't be allocated, otherwise the return value
  2043 	of the thread read operation, Kern::ThreadRead(), when reading from the source buffer.
  2044 */
  2045 EXPORT_C TInt DUsbClientController::SetCSInterfaceDescriptorBlock(DThread* aThread, const DBase* aClientId,
  2046 																  TInt aSettingNum,
  2047 																  const TDes8& aInterfaceDescriptor, TInt aSize)
  2048 	{
  2049 	__KTRACE_OPT(KUSB,
  2050 				 Kern::Printf("DUsbClientController::SetCSInterfaceDescriptorBlock(x, 0x%08x, %d, y, %d)",
  2051 							  aClientId, aSettingNum, aSize));
  2052 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  2053 	if (ifcset < 0)
  2054 		{
  2055 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  2056 		return KErrNotFound;
  2057 		}
  2058 	if (aSize < 2)
  2059 		{
  2060 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: aSize < 2 (%d)", aSize));
  2061 		return KErrArgument;
  2062 		}
  2063 	return iDescriptors.SetCSInterfaceDescriptorTC(aThread, aInterfaceDescriptor, ifcset, aSettingNum, aSize);
  2064 	}
  2065 
  2066 
  2067 /** Returns the total size all non-standard (class-specific) interface descriptors for a specific interface.
  2068 
  2069 	@param aThread A pointer to the thread the LDD requesting the descriptor block size is running in.
  2070 	@param aClientId A pointer to the LDD requesting the descriptor block size.
  2071 	@param aSettingNum The setting number of the interface for which the descriptor block size is
  2072 	requested.
  2073 	@param aSize A reference to a buffer into which the requested descriptor block size should be written (most
  2074 	likely located user-side).
  2075 
  2076 	@return KErrNotFound if the specified interface couldn't be found, otherwise the return value of the thread
  2077 	write operation, Kern::ThreadWrite(), when writing to the target buffer.
  2078 */
  2079 EXPORT_C TInt DUsbClientController::GetCSInterfaceDescriptorBlockSize(DThread* aThread, const DBase* aClientId,
  2080 																	  TInt aSettingNum, TDes8& aSize)
  2081 	{
  2082 	__KTRACE_OPT(KUSB,
  2083 				 Kern::Printf("DUsbClientController::GetCSInterfaceDescriptorBlockSize(x, 0x%08x, %d, y)",
  2084 							  aClientId, aSettingNum));
  2085 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  2086 	if (ifcset < 0)
  2087 		{
  2088 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  2089 		return KErrNotFound;
  2090 		}
  2091 	TInt s;
  2092 	const TInt r = iDescriptors.GetCSInterfaceDescriptorSize(ifcset, aSettingNum, s);
  2093 	if (r == KErrNone)
  2094 		{
  2095 		const TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
  2096 		Kern::ThreadDesWrite(aThread, &aSize, size, 0);
  2097 		}
  2098 	else
  2099 		{
  2100 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: cs interface descriptor not found"));
  2101 		}
  2102 	return r;
  2103 	}
  2104 
  2105 
  2106 /** Returns a block of all available non-standard (class-specific) endpoint descriptors for a specific endpoint.
  2107 
  2108 	@param aThread A pointer to the thread the LDD requesting the descriptor block is running in.
  2109 	@param aClientId A pointer to the LDD requesting the descriptor block.
  2110 	@param aSettingNum The setting number of the interface that contains the endpoint for which the
  2111 	descriptor block is requested.
  2112 	@param aEndpointNum The endpoint for which the descriptor block is requested.
  2113 	@param aEndpointDescriptor A reference to a buffer into which the requested descriptor(s) should be written
  2114 	(most likely located user-side).
  2115 
  2116 	@return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
  2117 	of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
  2118 */
  2119 EXPORT_C TInt DUsbClientController::GetCSEndpointDescriptorBlock(DThread* aThread, const DBase* aClientId,
  2120 																 TInt aSettingNum, TInt aEndpointNum,
  2121 																 TDes8& aEndpointDescriptor)
  2122 	{
  2123 	__KTRACE_OPT(KUSB,
  2124 				 Kern::Printf("DUsbClientController::GetCSEndpointDescriptorBlock(x, 0x%08x, %d, %d, y)",
  2125 							  aClientId, aSettingNum, aEndpointNum));
  2126 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  2127 	if (ifcset < 0)
  2128 		{
  2129 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  2130 		return KErrNotFound;
  2131 		}
  2132 	return iDescriptors.GetCSEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
  2133 												  aSettingNum, EpIdx2Addr(aEndpointNum));
  2134 	}
  2135 
  2136 
  2137 /** Sets a block of (i.e. one or more) non-standard (class-specific) endpoint descriptors for a specific
  2138 	endpoint.
  2139 
  2140 	@param aThread A pointer to the thread the LDD requesting the setting of the descriptor block is running
  2141 	in.
  2142 	@param aClientId A pointer to the LDD requesting the setting of the descriptor block.
  2143 	@param aSettingNum The setting number of the interface that contains the endpoint for which the
  2144 	descriptor block is to be set.
  2145 	@param aEndpointNum The endpoint for which the descriptor block is to be set.
  2146 	@param aEndpointDescriptor A reference to a buffer which contains the descriptor block to be set (most
  2147 	likely located user-side).
  2148 	@param aSize The size of the descriptor block to be set.
  2149 
  2150 	@return KErrNotFound if the specified interface or endpoint couldn't be found, KErrArgument if aSize is
  2151 	less than 2, KErrNoMemory if enough memory for the new descriptor(s) couldn't be allocated, otherwise the
  2152 	return value of the thread read operation, Kern::ThreadRead(), when reading from the source buffer.
  2153 */
  2154 EXPORT_C TInt DUsbClientController::SetCSEndpointDescriptorBlock(DThread* aThread, const DBase* aClientId,
  2155 																 TInt aSettingNum, TInt aEndpointNum,
  2156 																 const TDes8& aEndpointDescriptor, TInt aSize)
  2157 	{
  2158 	__KTRACE_OPT(KUSB,
  2159 				 Kern::Printf("DUsbClientController::SetCSEndpointDescriptorBlock(x, 0x%08x, %d, %d, y)",
  2160 							  aClientId, aSettingNum, aEndpointNum));
  2161 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  2162 	if (ifcset < 0)
  2163 		{
  2164 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  2165 		return KErrNotFound;
  2166 		}
  2167 	if (aSize < 2)
  2168 		{
  2169 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: aSize < 2 (%d)", aSize));
  2170 		return KErrArgument;
  2171 		}
  2172 	return iDescriptors.SetCSEndpointDescriptorTC(aThread, aEndpointDescriptor, ifcset,
  2173 												  aSettingNum, EpIdx2Addr(aEndpointNum), aSize);
  2174 	}
  2175 
  2176 
  2177 /** Returns the total size all non-standard (class-specific) endpoint descriptors for a specific endpoint.
  2178 
  2179 	@param aThread A pointer to the thread the LDD requesting the descriptor block size is running in.
  2180 	@param aClientId A pointer to the LDD requesting the descriptor block size.
  2181 	@param aSettingNum The setting number of the interface for which the descriptor block size is
  2182 	requested.
  2183 	@param aEndpointNum The endpoint for which the descriptor block size is requested.
  2184 	@param aSize A reference to a buffer into which the requested descriptor block size should be written (most
  2185 	likely located user-side).
  2186 
  2187 	@return KErrNotFound if the specified interface or endpoint couldn't be found, otherwise the return value
  2188 	of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
  2189 */
  2190 EXPORT_C TInt DUsbClientController::GetCSEndpointDescriptorBlockSize(DThread* aThread, const DBase* aClientId,
  2191 																	 TInt aSettingNum, TInt aEndpointNum,
  2192 																	 TDes8& aSize)
  2193 	{
  2194 	__KTRACE_OPT(KUSB,
  2195 				 Kern::Printf("DUsbClientController::GetCSEndpointDescriptorBlockSize(x, 0x%08x, %d, %d, y)",
  2196 							  aClientId, aSettingNum, aEndpointNum));
  2197 	const TInt ifcset = ClientId2InterfaceNumber(aClientId);
  2198 	if (ifcset < 0)
  2199 		{
  2200 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface not found from client ID"));
  2201 		return KErrNotFound;
  2202 		}
  2203 	TInt s;
  2204 	const TInt r = iDescriptors.GetCSEndpointDescriptorSize(ifcset, aSettingNum,
  2205 															EpIdx2Addr(aEndpointNum), s);
  2206 	if (r == KErrNone)
  2207 		{
  2208 		const TPtrC8 size(reinterpret_cast<const TUint8*>(&s), sizeof(s));
  2209 		Kern::ThreadDesWrite(aThread, &aSize, size, 0);
  2210 		}
  2211 	else
  2212 		{
  2213 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: cs endpoint descriptor not found"));
  2214 		}
  2215 	return r;
  2216 	}
  2217 
  2218 
  2219 /** Returns the currently set string descriptor language ID (LANGID) code.
  2220 
  2221 	@param aThread A pointer to the thread the LDD requesting the LANGID is running in.
  2222 	@param aLangId A reference to a buffer into which the requested code should be written (most likely
  2223 	located user-side).
  2224 
  2225 	@return The return value of the thread write operation, Kern::ThreadDesWrite(),
  2226 	when writing to the target buffer.
  2227 */
  2228 EXPORT_C TInt DUsbClientController::GetStringDescriptorLangId(DThread* aThread, TDes8& aLangId)
  2229 	{
  2230 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptorLangId()"));
  2231 	return iDescriptors.GetStringDescriptorLangIdTC(aThread, aLangId);
  2232 	}
  2233 
  2234 
  2235 /** Sets the string descriptor language ID (LANGID) code.
  2236 
  2237 	@param aLangId The langauge ID code to be written.
  2238 
  2239 	@return KErrNone.
  2240 */
  2241 EXPORT_C TInt DUsbClientController::SetStringDescriptorLangId(TUint16 aLangId)
  2242 	{
  2243 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptorLangId()"));
  2244 	return iDescriptors.SetStringDescriptorLangId(aLangId);
  2245 	}
  2246 
  2247 
  2248 /** Returns the currently set Manufacturer string (which is referenced by the iManufacturer field in the device
  2249 	descriptor).
  2250 
  2251 	(Thus, the function should actually be called either 'GetManufacturerString'
  2252 	or 'GetManufacturerStringDescriptorString'.)
  2253 
  2254 	@param aThread A pointer to the thread the LDD requesting the string is running in.
  2255 	@param aString A reference to a buffer into which the requested string should be written (most likely
  2256 	located user-side).
  2257 
  2258 	@return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
  2259 	value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
  2260 */
  2261 EXPORT_C TInt DUsbClientController::GetManufacturerStringDescriptor(DThread* aThread, TDes8& aString)
  2262 	{
  2263 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetManufacturerStringDescriptor()"));
  2264 	return iDescriptors.GetManufacturerStringDescriptorTC(aThread, aString);
  2265 	}
  2266 
  2267 
  2268 /** Sets a new Manufacturer string in the Manufacturer string descriptor (which is referenced by the
  2269 	iManufacturer field in the device descriptor).
  2270 
  2271 	(Thus, the function should actually be called either
  2272 	'SetManufacturerString' or 'SetManufacturerStringDescriptorString'.)
  2273 
  2274 	@param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
  2275 	@param aString A reference to a buffer which contains the string to be set (most likely located
  2276 	user-side).
  2277 
  2278 	@return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
  2279 	return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
  2280 	KErrNone if new string descriptor successfully set.
  2281 */
  2282 EXPORT_C TInt DUsbClientController::SetManufacturerStringDescriptor(DThread* aThread, const TDes8& aString)
  2283 	{
  2284 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetManufacturerStringDescriptor()"));
  2285 	return iDescriptors.SetManufacturerStringDescriptorTC(aThread, aString);
  2286 	}
  2287 
  2288 
  2289 /** Removes (deletes) the Manufacturer string descriptor (which is referenced by the
  2290 	iManufacturer field in the device descriptor).
  2291 
  2292 	@return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
  2293 */
  2294 EXPORT_C TInt DUsbClientController::RemoveManufacturerStringDescriptor()
  2295 	{
  2296 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveManufacturerStringDescriptor()"));
  2297 	return iDescriptors.RemoveManufacturerStringDescriptor();
  2298 	}
  2299 
  2300 
  2301 /** Returns the currently set Product string (which is referenced by the iProduct field in the device
  2302 	descriptor).
  2303 
  2304 	(Thus, the function should actually be called either 'GetProductString' or
  2305 	'GetProductStringDescriptorString'.)
  2306 
  2307 	@param aThread A pointer to the thread the LDD requesting the string is running in.
  2308 	@param aString A reference to a buffer into which the requested string should be written (most likely
  2309 	located user-side).
  2310 
  2311 	@return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
  2312 	value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
  2313 */
  2314 EXPORT_C TInt DUsbClientController::GetProductStringDescriptor(DThread* aThread, TDes8& aString)
  2315 	{
  2316 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetProductStringDescriptor()"));
  2317 	return iDescriptors.GetProductStringDescriptorTC(aThread, aString);
  2318 	}
  2319 
  2320 
  2321 /** Sets a new Product string in the Product string descriptor (which is referenced by the iProduct field in
  2322 	the device descriptor).
  2323 
  2324 	(Thus, the function should actually be called either 'SetProductString' or
  2325 	'SetProductStringDescriptorString'.)
  2326 
  2327 	@param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
  2328 	@param aString A reference to a buffer which contains the string to be set (most likely located
  2329 	user-side).
  2330 
  2331 	@return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
  2332 	return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
  2333 	KErrNone if new string descriptor successfully set.
  2334 */
  2335 EXPORT_C TInt DUsbClientController::SetProductStringDescriptor(DThread* aThread, const TDes8& aString)
  2336 	{
  2337 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetProductStringDescriptor()"));
  2338 	return iDescriptors.SetProductStringDescriptorTC(aThread, aString);
  2339 	}
  2340 
  2341 
  2342 /** Removes (deletes) the Product string descriptor (which is referenced by the
  2343 	iProduct field in the device descriptor).
  2344 
  2345 	@return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
  2346 */
  2347 EXPORT_C TInt DUsbClientController::RemoveProductStringDescriptor()
  2348 	{
  2349 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveProductStringDescriptor()"));
  2350 	return iDescriptors.RemoveProductStringDescriptor();
  2351 	}
  2352 
  2353 
  2354 /** Returns the currently set SerialNumber string (which is referenced by the iSerialNumber field in the device
  2355 	descriptor).
  2356 
  2357 	(Thus, the function should actually be called either 'GetSerialNumberString' or
  2358 	'GetSerialNumberStringDescriptorString'.)
  2359 
  2360 	@param aThread A pointer to the thread the LDD requesting the string is running in.
  2361 	@param aString A reference to a buffer into which the requested string should be written (most likely
  2362 	located user-side).
  2363 
  2364 	@return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
  2365 	value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
  2366 */
  2367 EXPORT_C TInt DUsbClientController::GetSerialNumberStringDescriptor(DThread* aThread, TDes8& aString)
  2368 	{
  2369 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetSerialNumberStringDescriptor()"));
  2370 	return iDescriptors.GetSerialNumberStringDescriptorTC(aThread, aString);
  2371 	}
  2372 
  2373 
  2374 /** Sets a new SerialNumber string in the SerialNumber string descriptor (which is referenced by the
  2375 	iSerialNumber field in the device descriptor).
  2376 
  2377 	(Thus, the function should actually be called either
  2378 	'SetSerialNumberString' or 'SetSerialNumberStringDescriptorString'.)
  2379 
  2380 	@param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
  2381 	@param aString A reference to a buffer which contains the string to be set (most likely located
  2382 	user-side).
  2383 
  2384 	@return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
  2385 	return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
  2386 	KErrNone if new string descriptor successfully set.
  2387 */
  2388 EXPORT_C TInt DUsbClientController::SetSerialNumberStringDescriptor(DThread* aThread, const TDes8& aString)
  2389 	{
  2390 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetSerialNumberStringDescriptor()"));
  2391 	return iDescriptors.SetSerialNumberStringDescriptorTC(aThread, aString);
  2392 	}
  2393 
  2394 
  2395 /** Removes (deletes) the Serial Number string descriptor (which is referenced by the
  2396 	iSerialNumber field in the device descriptor).
  2397 
  2398 	@return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found
  2399 */
  2400 EXPORT_C TInt DUsbClientController::RemoveSerialNumberStringDescriptor()
  2401 	{
  2402 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveSerialNumberStringDescriptor()"));
  2403 	return iDescriptors.RemoveSerialNumberStringDescriptor();
  2404 	}
  2405 
  2406 
  2407 /** Returns the currently set Configuration string (which is referenced by the iConfiguration field in the
  2408 	configuration descriptor).
  2409 
  2410 	(Thus, the function should actually be called either 'GetConfigurationString' or
  2411 	'GetConfigurationStringDescriptorString'.)
  2412 
  2413 	@param aThread A pointer to the thread the LDD requesting the string is running in.
  2414 	@param aString A reference to a buffer into which the requested string should be written (most likely
  2415 	located user-side).
  2416 
  2417 	@return KErrNotFound if the string descriptor couldn't be found (PIL internal error), otherwise the return
  2418 	value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
  2419 */
  2420 EXPORT_C TInt DUsbClientController::GetConfigurationStringDescriptor(DThread* aThread, TDes8& aString)
  2421 	{
  2422 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetConfigurationStringDescriptor()"));
  2423 	return iDescriptors.GetConfigurationStringDescriptorTC(aThread, aString);
  2424 	}
  2425 
  2426 
  2427 /** Sets a new Configuration string in the Configuration string descriptor (which is referenced by the
  2428 	iConfiguration field in the configuration descriptor).
  2429 
  2430 	(Thus, the function should actually be called either
  2431 	'SetConfigurationString' or 'SetConfigurationStringDescriptorString'.)
  2432 
  2433 	@param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
  2434 	@param aString A reference to a buffer which contains the string to be set (most likely located
  2435 	user-side).
  2436 
  2437 	@return KErrNoMemory if not enough memory for the new descriptor or the string could be allocated, the
  2438 	return value of the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong,
  2439 	KErrNone if new string descriptor successfully set.
  2440 */
  2441 EXPORT_C TInt DUsbClientController::SetConfigurationStringDescriptor(DThread* aThread, const TDes8& aString)
  2442 	{
  2443 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetConfigurationStringDescriptor()"));
  2444 	return iDescriptors.SetConfigurationStringDescriptorTC(aThread, aString);
  2445 	}
  2446 
  2447 
  2448 /** Removes (deletes) the Configuration string descriptor (which is referenced by the
  2449 	iConfiguration field in the configuration descriptor).
  2450 
  2451 	@return KErrNone if successful, KErrNotFound if the string descriptor couldn't be found.
  2452 */
  2453 EXPORT_C TInt DUsbClientController::RemoveConfigurationStringDescriptor()
  2454 	{
  2455 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveConfigurationStringDescriptor()"));
  2456 	return iDescriptors.RemoveConfigurationStringDescriptor();
  2457 	}
  2458 
  2459 
  2460 /** Copies the string descriptor at the specified index in the string descriptor array into
  2461 	the aString argument.
  2462 
  2463 	@param aIndex The position of the string descriptor in the string descriptor array.
  2464 	@param aThread A pointer to the thread the LDD requesting the string is running in.
  2465 	@param aString A reference to a buffer into which the requested string should be written (most likely
  2466 	located user-side).
  2467 
  2468 	@return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index, or the
  2469 	return value of the thread write operation, Kern::ThreadWrite(), when writing to the target buffer.
  2470 */
  2471 EXPORT_C TInt DUsbClientController::GetStringDescriptor(DThread* aThread, TUint8 aIndex, TDes8& aString)
  2472 	{
  2473 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::GetStringDescriptor(%d)", aIndex));
  2474 	return iDescriptors.GetStringDescriptorTC(aThread, aIndex, aString);
  2475 	}
  2476 
  2477 
  2478 /** Sets the aString argument to be a string descriptor at the specified index in the string
  2479 	descriptor array. If a string descriptor already exists at that position then it will be replaced.
  2480 
  2481 	@param aIndex The position of the string descriptor in the string descriptor array.
  2482 	@param aThread A pointer to the thread the LDD requesting the setting of the string is running in.
  2483 	@param aString A reference to a buffer which contains the string to be set (most likely located
  2484 	user-side).
  2485 
  2486 	@return KErrNone if successful, KErrArgument if aIndex is invalid, KErrNoMemory if no memory is available
  2487 	to store the new string (an existing descriptor at that index will be preserved), or the return value of
  2488 	the thread read operation, Kern::ThreadRead(), if reading from the source buffer goes wrong.
  2489 */
  2490 EXPORT_C TInt DUsbClientController::SetStringDescriptor(DThread* aThread, TUint8 aIndex, const TDes8& aString)
  2491 	{
  2492 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetStringDescriptor(%d)", aIndex));
  2493 	return iDescriptors.SetStringDescriptorTC(aThread, aIndex, aString);
  2494 	}
  2495 
  2496 
  2497 /** Removes (deletes) the string descriptor at the specified index in the string descriptor array.
  2498 
  2499 	@param aIndex The position of the string descriptor in the string descriptor array.
  2500 
  2501 	@return KErrNone if successful, KErrNotFound if no string descriptor exists at the specified index.
  2502 */
  2503 EXPORT_C TInt DUsbClientController::RemoveStringDescriptor(TUint8 aIndex)
  2504 	{
  2505 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RemoveStringDescriptor(%d)", aIndex));
  2506 	return iDescriptors.RemoveStringDescriptor(aIndex);
  2507 	}
  2508 
  2509 
  2510 /** Allocates an endpoint resource.
  2511 
  2512 	If the resource gets successfully allocated, it will be used from when the current bus transfer
  2513 	has been completed.
  2514 
  2515 	@param aClientId A pointer to the LDD requesting the endpoint resource.
  2516 	@param aEndpointNum The number of the endpoint.
  2517 	@param aResource The endpoint resource to be allocated.
  2518 
  2519 	@return KErrNone if the resource has been successfully allocated, KErrNotSupported if the endpoint
  2520 	does not support the resource requested, and KErrInUse if the resource is already consumed and
  2521 	cannot be allocated. KErrArgument if the endpoint number is invalid.
  2522 */
  2523 EXPORT_C TInt DUsbClientController::AllocateEndpointResource(const DBase* /*aClientId*/, TInt aEndpointNum,
  2524 															 TUsbcEndpointResource aResource)
  2525 	{
  2526 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::AllocateEndpointResource()"));
  2527 	return AllocateEndpointResource(aEndpointNum, aResource);
  2528 	}
  2529 
  2530 
  2531 /** Deallocates (frees) an endpoint resource.
  2532 
  2533 	The resource will be removed from when the current bus transfer has been completed.
  2534 
  2535 	@param aClientId A pointer to the LDD requesting the freeing of the endpoint resource.
  2536 	@param aEndpointNum The number of the endpoint.
  2537 	@param aResource The endpoint resource to be deallocated.
  2538 
  2539 	@return KErrNone if the resource has been successfully deallocated, KErrNotSupported if the endpoint
  2540 	does not support the resource requested. KErrArgument if the endpoint number is invalid.
  2541 */
  2542 EXPORT_C TInt DUsbClientController::DeAllocateEndpointResource(const DBase* /*aClientId*/, TInt aEndpointNum,
  2543 															   TUsbcEndpointResource aResource)
  2544 	{
  2545 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeAllocateEndpointResource()"));
  2546 	return DeAllocateEndpointResource(aEndpointNum, aResource);
  2547 	}
  2548 
  2549 
  2550 /** Queries the use of and endpoint resource.
  2551 
  2552 	If the resource gets successfully allocated, it will be used from when the current bus transfer
  2553 	has been completed.
  2554 
  2555 	@param aClientId A pointer to the LDD querying the endpoint resource.
  2556 	@param aEndpointNum The number of the endpoint.
  2557 	@param aResource The endpoint resource to be queried.
  2558 
  2559 	@return ETrue if the specified resource is in use at the endpoint, EFalse if not or if there was any error
  2560 	during the execution of the function.
  2561 */
  2562 EXPORT_C TBool DUsbClientController::QueryEndpointResource(const DBase* /*aClientId*/, TInt aEndpointNum,
  2563 														   TUsbcEndpointResource aResource)
  2564 	{
  2565 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::QueryEndpointResource()"));
  2566 	return QueryEndpointResource(aEndpointNum, aResource);
  2567 	}
  2568 
  2569 
  2570 EXPORT_C TInt DUsbClientController::EndpointPacketSize(const DBase* aClientId, TInt aEndpointNum)
  2571 	{
  2572 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointPacketSize(0x%08x, %d)",
  2573 									aClientId, aEndpointNum));
  2574 
  2575 	const TUsbcInterfaceSet* const ifcset_ptr = ClientId2InterfacePointer(aClientId);
  2576 	if (!ifcset_ptr)
  2577 		{
  2578 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface or clientid not found"));
  2579 		return -1;
  2580 		}
  2581 	const TUsbcInterface* const ifc_ptr = ifcset_ptr->iInterfaces[ifcset_ptr->iCurrentInterface];
  2582 	const RPointerArray<TUsbcLogicalEndpoint>& ep_array = ifc_ptr->iEndpoints;
  2583 	const TInt n = ep_array.Count();
  2584 	for (TInt i = 0; i < n; i++)
  2585 		{
  2586 		const TUsbcLogicalEndpoint* const ep = ep_array[i];
  2587 		if (EpAddr2Idx(ep->iPEndpoint->iEndpointAddr) == static_cast<TUint>(aEndpointNum))
  2588 			{
  2589 			__KTRACE_OPT(KUSB, Kern::Printf("  Endpoint packet sizes: FS = %d  HS = %d",
  2590 											ep->iEpSize_Fs, ep->iEpSize_Hs));
  2591 			const TInt size = iHighSpeed ? ep->iEpSize_Hs : ep->iEpSize_Fs;
  2592 			__KTRACE_OPT(KUSB, Kern::Printf("  Returning %d", size));
  2593 			return size;
  2594 			}
  2595 		}
  2596 	__KTRACE_OPT(KPANIC, Kern::Printf("  Error: endpoint not found"));
  2597 	return -1;
  2598 	}
  2599 
  2600 
  2601 //
  2602 // === USB Controller member function implementations - LDD API (public) ===========================
  2603 //
  2604 
  2605 EXPORT_C TBool DUsbClientController::CurrentlyUsingHighSpeed()
  2606 	{
  2607 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CurrentlyUsingHighSpeed()"));
  2608 	return EFalse;
  2609 	}
  2610 
  2611 
  2612 //
  2613 // === USB Controller member function implementations - PSL API (public) ===========================
  2614 //
  2615 
  2616 /** Gets called by the PSL to register a newly created derived class controller object.
  2617 
  2618 	@param aUdc The number of the new UDC. It should be 0 for the first (or only) UDC in the system, 1 for the
  2619 	second one, and so forth. KUsbcMaxUdcs determines how many UDCs are supported.
  2620 
  2621 	@return A pointer to the controller if successfully registered, NULL if aUdc out of (static) range.
  2622 
  2623 	@publishedPartner @released
  2624 */
  2625 DUsbClientController* DUsbClientController::RegisterUdc(TInt aUdc)
  2626 	{
  2627 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RegisterUdc()"));
  2628 	if (aUdc < 0 || aUdc > (KUsbcMaxUdcs - 1))
  2629 		{
  2630 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: aUdc out of range (%d)", aUdc));
  2631 		return NULL;
  2632 		}
  2633 	return UsbClientController[aUdc] = this;
  2634 	}
  2635 
  2636 
  2637 //
  2638 // === USB Controller member function implementations - PSL API (protected) ========================
  2639 //
  2640 
  2641 /** Initialises an instance of this class, which is the base class of the derived class (= PSL, which is
  2642 	supposed to call this function).
  2643 
  2644 	It does the following things:
  2645 
  2646 	- disconnects the UDC from the bus,
  2647 	- initialises the USB descriptor pool, uses data from the PSL (see function argument list)
  2648 	- creates and initialises the basic USB device configuration
  2649 	- initialises the array of physical endpoints
  2650 	- initialises Ep0 structures (but doesn't configure & enable Ep0 yet)
  2651 	- creates and installs the USB power handler
  2652 
  2653 	@param aDeviceDesc A pointer to a valid standard USB device descriptor or NULL. The values initially
  2654 	required in the descriptor follow from its constructor. The descriptor is not copied over, but rather this
  2655 	pointer is queued directly into the descriptor pool. Must be writable memory.
  2656 
  2657 	@param aConfigDesc A pointer to a valid standard USB configuration descriptor or NULL. The values
  2658 	initially required in the descriptor follow from its constructor. The descriptor is not copied over, but
  2659 	rather this pointer is queued directly into the descriptor pool. Must be writable memory.
  2660 
  2661 	@param aLangId A pointer to a valid USB language ID (string) descriptor. The values initially required in
  2662 	the descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
  2663 	queued directly into the descriptor pool. Must be writable memory. Other than the remaining four string
  2664 	descriptors, this one is not optional. The reason is that the USB spec mandates a LangId descriptor as
  2665 	soon as a single string descriptor gets returned by the device. So, even though the device might omit the
  2666 	Manufacturer, Product, SerialNumber, and Configuration string descriptors, it is at this point not known
  2667 	whether there will be any Interface string descriptors. Since any USB API user can create an interface
  2668 	with an Interface string descriptor, we have to insist here on the provision of a LangId string
  2669 	descriptor. (The PIL decides at run-time whether or not to return the LangId string descriptor to the
  2670 	host, depending on whether there exist any string descriptors at that time.)
  2671 
  2672 	@param aManufacturer A pointer to a valid USB string descriptor or NULL. The values initially required in
  2673 	the descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
  2674 	queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
  2675 	the iManufacturer field in the device descriptor.
  2676 
  2677 	@param aProduct A pointer to a valid USB string descriptor or NULL. The values initially required in the
  2678 	descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
  2679 	queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
  2680 	the iProduct field in the device descriptor.
  2681 
  2682 	@param aSerialNum A pointer to a valid USB string descriptor or NULL. The values initially required in the
  2683 	descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
  2684 	queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
  2685 	the iSerialNumber field in the device descriptor.
  2686 
  2687 	@param aConfig A pointer to a valid USB string descriptor or NULL. The values initially required in the
  2688 	descriptor follow from its constructor. The descriptor is not copied over, but rather this pointer is
  2689 	queued directly into the descriptor pool. Must be writable memory. This descriptor will be referenced by
  2690 	the iConfiguration field in the configuration descriptor.
  2691 
  2692 	@param aOtgDesc A pointer to a valid USB OTG descriptor (if OTG is supported by this device and is to be
  2693 	supported by the driver) or NULL. The values initially required in the descriptor follow from its
  2694 	constructor. The descriptor is not copied over, but rather this pointer is queued directly into the
  2695 	descriptor pool. Must be writable memory.
  2696 
  2697 	@return EFalse, if USB descriptor pool initialisation fails, or if configuration creation fails, or if the
  2698 	PSL reports more endpoints than the constant KUsbcMaxEndpoints permits, or if the Ep0 logical endpoint
  2699 	creation fails, or if the creation of the power handler fails; ETrue, if base class object successfully
  2700 	initialised.
  2701 
  2702 	@publishedPartner @released
  2703 */
  2704 TBool DUsbClientController::InitialiseBaseClass(TUsbcDeviceDescriptor* aDeviceDesc,
  2705 												TUsbcConfigDescriptor* aConfigDesc,
  2706 												TUsbcLangIdDescriptor* aLangId,
  2707 												TUsbcStringDescriptor* aManufacturer,
  2708 												TUsbcStringDescriptor* aProduct,
  2709 												TUsbcStringDescriptor* aSerialNum,
  2710 												TUsbcStringDescriptor* aConfig,
  2711                                                 TUsbcOtgDescriptor* aOtgDesc)
  2712 	{
  2713 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InitialiseBaseClass()"));
  2714 	// We don't want the host to see us (at least not yet):
  2715 	UsbDisconnect();
  2716 
  2717 	// Initialise USB descriptor pool
  2718 	if (iDescriptors.Init(aDeviceDesc, aConfigDesc, aLangId, aManufacturer, aProduct,
  2719 						  aSerialNum, aConfig, aOtgDesc) !=	KErrNone)
  2720 		{
  2721 		__KTRACE_OPT(KUSB, Kern::Printf("  Error: Descriptor initialization failed"));
  2722 		return EFalse;
  2723 		}
  2724 
  2725 	if (aOtgDesc)
  2726 		{
  2727 		iOtgSupport = ETrue;
  2728 		iOtgFuncMap = aOtgDesc->DescriptorData()[2];
  2729 		// We're only interested in the following capability if this is
  2730 		// actually an OTG device.
  2731 		iOtgHnpHandledByHw = DeviceHnpHandledByHardwareCaps();
  2732 		}
  2733 
  2734 	// Some member variables
  2735 	iSelfPowered  = aConfigDesc->Byte(7) & (1 << 6);		// Byte 7: bmAttributes
  2736 	iRemoteWakeup = aConfigDesc->Byte(7) & (1 << 5);
  2737 	iRmWakeupStatus_Enabled = EFalse;						// default
  2738 
  2739 	if (DeviceHighSpeedCaps())
  2740 		{
  2741 		if (iDescriptors.InitHs() != KErrNone)
  2742 			{
  2743 			return EFalse;
  2744 			}
  2745 		}
  2746 
  2747 	// Create and initialise our first (and only) configuration
  2748 	TUsbcConfiguration* config = new TUsbcConfiguration(1);
  2749 	if (!config)
  2750 		{
  2751 		return EFalse;
  2752 		}
  2753 	iConfigs.Append(config);
  2754 
  2755 	// Some variable initializations (needed here because of the goto's)
  2756 	const TUsbcEndpointCaps* caps = NULL;
  2757 	TUsbcEndpointInfo info(KUsbEpTypeControl, KUsbEpDirOut, 0);
  2758 	TUsbcLogicalEndpoint* ep = NULL;
  2759 
  2760 	// Initialise the array of physical endpoints
  2761 	iDeviceTotalEndpoints = DeviceTotalEndpoints();
  2762 	__KTRACE_OPT(KUSB, Kern::Printf("  DeviceTotalEndpoints: %d", iDeviceTotalEndpoints));
  2763 	// KUsbcMaxEndpoints doesn't include ep 0
  2764 	if ((iDeviceTotalEndpoints > (KUsbcMaxEndpoints + 2)) ||
  2765 		((iDeviceTotalEndpoints * sizeof(TUsbcPhysicalEndpoint)) > sizeof(iRealEndpoints)))
  2766 		{
  2767 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: too many endpoints! (change KUsbcMaxEndpoints: %d)",
  2768 										  KUsbcMaxEndpoints));
  2769 		goto exit_1;
  2770 		}
  2771 	caps = DeviceEndpointCaps();
  2772 	for (TInt i = 0; i < iDeviceTotalEndpoints; ++i)
  2773 		{
  2774 		iRealEndpoints[i].iEndpointAddr = EpIdx2Addr(i);
  2775 		__KTRACE_OPT(KUSB, Kern::Printf("  Caps[%02d] - iTypes: 0x%08x iSizes: 0x%08x",
  2776 										i, caps[i].iTypesAndDir, caps[i].iSizes));
  2777 		iRealEndpoints[i].iCaps = caps[i];
  2778 		iRealEndpoints[i].iCaps.iReserved[0] = 0;
  2779 		iRealEndpoints[i].iCaps.iReserved[1] = 0;
  2780 		if ((i > 1) && (caps[i].iTypesAndDir != KUsbEpNotAvailable))
  2781 			{
  2782 			__KTRACE_OPT(KUSB, Kern::Printf("  --> UsableEndpoint: #%d", i));
  2783 			iDeviceUsableEndpoints++;
  2784 			}
  2785 		}
  2786 
  2787 	// Initialise Ep0 structures (logical endpoints are numbered 1..KMaxEndpointsPerClient,
  2788 	// and virtual 0 is real 0):
  2789 	// -- Ep0 OUT
  2790 	iEp0MaxPacketSize = caps[0].MaxPacketSize();
  2791 	__KTRACE_OPT(KUSB, Kern::Printf("  using Ep0 maxpacketsize of %d bytes", iEp0MaxPacketSize));
  2792 	info.iSize = iEp0MaxPacketSize;
  2793 	ep = new TUsbcLogicalEndpoint(this, 0, info, NULL, &iRealEndpoints[KEp0_Out]);
  2794 	if (!ep)
  2795 		{
  2796 		goto exit_1;
  2797 		}
  2798 	__KTRACE_OPT(KUSB, Kern::Printf("  creating ep: mapping real ep %d --> logical ep 0", KEp0_Out));
  2799 	iRealEndpoints[KEp0_Out].iLEndpoint = ep;
  2800 	// -- Ep0 IN
  2801 	info.iDir = KUsbEpDirIn;
  2802 	ep = new TUsbcLogicalEndpoint(this, 0, info, NULL, &iRealEndpoints[KEp0_In]);
  2803 	if (!ep)
  2804 		{
  2805 		goto exit_2;
  2806 		}
  2807 	__KTRACE_OPT(KUSB, Kern::Printf("  creating ep: mapping real ep %d --> logical ep 0", KEp0_In));
  2808 	iRealEndpoints[KEp0_In].iLEndpoint = ep;
  2809 
  2810 	// Create the power handler
  2811 	iPowerHandler = new DUsbcPowerHandler(this);
  2812 	if (!iPowerHandler)
  2813 		{
  2814 		goto exit_3;
  2815 		}
  2816 	iPowerHandler->Add();
  2817 
  2818 	// Misc stuff
  2819 	iTrackDeviceState = DeviceStateChangeCaps();
  2820 	if (!iTrackDeviceState)
  2821 		{
  2822 		// There shouldn't really be any PSL that doesn't support Device State
  2823 		// tracking, but we cannot simply enforce it as we have to preserve
  2824 		// backwards compatibility.
  2825 		__KTRACE_OPT(KUSB, Kern::Printf("  Warning: USB Device State tracking not supported by PSL"));
  2826 		}
  2827 
  2828 	return ETrue;
  2829 
  2830  exit_3:
  2831 	delete iRealEndpoints[KEp0_In].iLEndpoint;
  2832  exit_2:
  2833 	delete iRealEndpoints[KEp0_Out].iLEndpoint;
  2834  exit_1:
  2835 	iConfigs.ResetAndDestroy();
  2836 
  2837 	return EFalse;
  2838 	}
  2839 
  2840 
  2841 /** The standard constructor for this class.
  2842 
  2843 	@publishedPartner @released
  2844  */
  2845 DUsbClientController::DUsbClientController()
  2846 	: iEp0ReceivedNonStdRequest(EFalse),
  2847 	  iRmWakeupStatus_Enabled(EFalse),
  2848 	  iEp0_RxBuf(),
  2849 	  iDeviceTotalEndpoints(0),
  2850 	  iDeviceUsableEndpoints(0),
  2851 	  iDeviceState(EUsbcDeviceStateUndefined),
  2852 	  iDeviceStateB4Suspend(EUsbcDeviceStateUndefined),
  2853 	  iSelfPowered(EFalse),
  2854 	  iRemoteWakeup(EFalse),
  2855 	  iTrackDeviceState(EFalse),
  2856 	  iHardwareActivated(EFalse),
  2857 	  iOtgSupport(EFalse),
  2858 	  iOtgHnpHandledByHw(EFalse),
  2859 	  iOtgFuncMap(0),
  2860 	  iHighSpeed(EFalse),
  2861 	  iSetup(),
  2862 	  iEp0MaxPacketSize(0),
  2863 	  iEp0ClientId(NULL),
  2864 	  iEp0DataReceived(0),
  2865 	  iEp0DataReceiving(EFalse),
  2866 	  iEp0WritePending(EFalse),
  2867 	  iEp0ClientDataTransmitting(EFalse),
  2868 	  iEp0DeviceControl(NULL),
  2869 	  iDescriptors(iEp0_TxBuf),
  2870 	  iCurrentConfig(0),
  2871 	  iConfigs(1),
  2872 	  iRealEndpoints(),
  2873 	  iEp0_TxBuf(),
  2874 	  iEp0_RxExtraCount(0),
  2875 	  iEp0_RxExtraData(EFalse),
  2876 	  iEp0_TxNonStdCount(0),
  2877 	  iEp0ReadRequestCallbacks(_FOFF(TUsbcRequestCallback, iLink)),
  2878 	  iClientCallbacks(_FOFF(TUsbcClientCallback, iLink)),
  2879 	  iStatusCallbacks(_FOFF(TUsbcStatusCallback, iLink)),
  2880 	  iEpStatusCallbacks(_FOFF(TUsbcEndpointStatusCallback, iLink)),
  2881 	  iOtgCallbacks(_FOFF(TUsbcOtgFeatureCallback, iLink)),
  2882 	  iReconnectTimer(ReconnectTimerCallback, this),
  2883 	  iCableStatusTimer(CableStatusTimerCallback, this),
  2884 	  iPowerUpDfc(PowerUpDfc, this, 3),
  2885 	  iPowerDownDfc(PowerDownDfc, this, 3),
  2886 	  iStandby(EFalse),
  2887 #ifdef USB_OTG_CLIENT
  2888 	  // In the OTG case the device starts out disabled
  2889 	  iStackIsActive(EFalse),
  2890 #else
  2891 	  iStackIsActive(ETrue),
  2892 #endif // USB_OTG_CLIENT
  2893 	  iOtgClientConnect(EFalse),
  2894 	  iClientSupportReady(EFalse),
  2895 	  iDPlusEnabled(EFalse),
  2896 	  iUsbResetDeferred(EFalse),
  2897 	  iEnablePullUpOnDPlus(NULL),
  2898 	  iDisablePullUpOnDPlus(NULL),
  2899 	  iOtgContext(NULL)
  2900 	{
  2901 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DUsbClientController()"));
  2902 
  2903 #ifndef SEPARATE_USB_DFC_QUEUE
  2904 	iPowerUpDfc.SetDfcQ(Kern::DfcQue0());
  2905   	iPowerDownDfc.SetDfcQ(Kern::DfcQue0());
  2906 #endif // SEPARATE_USB_DFC_QUEUE
  2907 
  2908 	for (TInt i = 0; i < KUsbcEpArraySize; i++)
  2909 		iRequestCallbacks[i] = NULL;
  2910 	}
  2911 
  2912 
  2913 /** This function gets called by the PSL upon detection of either of the following events:
  2914 	- USB Reset,
  2915 	- USB Suspend event,
  2916 	- USB Resume signalling,
  2917 	- The USB cable has been attached (inserted) or detached (removed).
  2918 
  2919 	@param anEvent An enum denoting the event that has occured.
  2920 
  2921 	@return KErrArgument if the event is not recognized, otherwise KErrNone.
  2922 
  2923 	@publishedPartner @released
  2924 */
  2925 TInt DUsbClientController::DeviceEventNotification(TUsbcDeviceEvent anEvent)
  2926 	{
  2927 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceEventNotification()"));
  2928 
  2929 	// This function may be called by the PSL from within an ISR -- so we have
  2930 	// to take care what we do here (and also in all functions that get called
  2931 	// from here).
  2932 
  2933 	switch (anEvent)
  2934 		{
  2935 	case EUsbEventSuspend:
  2936 		return ProcessSuspendEvent();
  2937 	case EUsbEventResume:
  2938 		return ProcessResumeEvent();
  2939 	case EUsbEventReset:
  2940 		return ProcessResetEvent();
  2941 	case EUsbEventCableInserted:
  2942 		return ProcessCableInsertEvent();
  2943 	case EUsbEventCableRemoved:
  2944 		return ProcessCableRemoveEvent();
  2945 		}
  2946 	return KErrArgument;
  2947 	}
  2948 
  2949 
  2950 /** This function gets called by the PSL upon completion of a pending data transfer request.
  2951 
  2952 	This function is not to be used for endpoint zero completions (use Ep0RequestComplete instead).
  2953 
  2954 	@param aCallback A pointer to a data transfer request callback structure which was previously passed to
  2955 	the PSL in a SetupReadBuffer() or SetupWriteBuffer() call.
  2956 
  2957 	@publishedPartner @released
  2958 */
  2959 void DUsbClientController::EndpointRequestComplete(TUsbcRequestCallback* aCallback)
  2960 	{
  2961 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EndpointRequestComplete(%p)", aCallback));
  2962 
  2963 	// This function may be called by the PSL from within an ISR -- so we have
  2964 	// to take care what we do here (and also in all functions that get called
  2965 	// from here).
  2966 
  2967 	// We don't test aCallback for NULL here (and therefore risk a crash)
  2968 	// because the PSL should never give us a NULL argument. If it does it
  2969 	// means the PSL is buggy and ought to be fixed.
  2970 	ProcessDataTransferDone(*aCallback);
  2971 	}
  2972 
  2973 
  2974 /** This function should be called by the PSL after reception of an Ep0
  2975 	SET_FEATURE request with a feature selector of either {b_hnp_enable,
  2976 	a_hnp_support, a_alt_hnp_support}, but only when that Setup packet is not
  2977 	handed up to the PIL (for instance because it is auto-decoded and
  2978 	'swallowed' by the UDC hardware).
  2979 
  2980 	@param aHnpState A bitmask indicating the present state of the three OTG
  2981 	feature selectors as follows:
  2982 
  2983 	bit.0 == a_alt_hnp_support
  2984 	bit.1 == a_hnp_support
  2985 	bit.2 == b_hnp_enable
  2986 
  2987 	@see DUsbClientController::ProcessSetClearDevFeature()
  2988 
  2989 	@publishedPartner @released
  2990 */
  2991 void DUsbClientController::HandleHnpRequest(TInt aHnpState)
  2992 // This function is called by the PSL from within an ISR -- so we have to take care what we do here
  2993 // (and also in all functions that get called from here).
  2994 	{
  2995 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::HandleHnpRequest(%d)", aHnpState));
  2996 
  2997 	if (!iOtgSupport)
  2998 		{
  2999 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only supported on a OTG device"));
  3000 		return;
  3001 		}
  3002 	if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
  3003 		{
  3004 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only valid if OTG device supports HNP"));
  3005 		return;
  3006 		}
  3007 	//	(case KUsbFeature_B_HnpEnable:)
  3008 	if (aHnpState & 0x04)
  3009 		{
  3010 		iOtgFuncMap |= KUsbOtgAttr_B_HnpEnable;
  3011 		}
  3012 	// (case KUsbFeature_A_HnpSupport:)
  3013 	if (aHnpState & 0x02)
  3014 		{
  3015 		iOtgFuncMap |= KUsbOtgAttr_A_HnpSupport;
  3016 		}
  3017 	// (case KUsbFeature_A_AltHnpSupport:)
  3018 	if (aHnpState & 0x01)
  3019 		{
  3020 		iOtgFuncMap |= KUsbOtgAttr_A_AltHnpSupport;
  3021 		}
  3022 	OtgFeaturesNotify();
  3023 	}
  3024 
  3025 
  3026 /** This function gets called by the PSL upon completion of a pending endpoint zero data transfer request.
  3027 
  3028 	@param aRealEndpoint Either 0 for Ep0 OUT (= Read), or 1 for Ep0 IN (= Write).
  3029 	@param aCount The number of bytes received or transmitted, respectively.
  3030 	@param aError The error status of the completed transfer request. Can be KErrNone if no error, KErrCancel
  3031 	if transfer was cancelled, or KErrPrematureEnd if a premature status end was encountered.
  3032 
  3033 	@return KErrNone if no error during transfer completion processing, KErrGeneral if the request was a read &
  3034 	a Setup packet was received & the recipient for that packet couldn't be found (invalid packet: Ep0 has been
  3035 	stalled), KErrNotFound if the request was a read & the recipient for that packet (Setup or data) _was_
  3036 	found - however no read had been set up by that recipient (this case should be used by the PSL to disable
  3037 	the Ep0 interrupt at that point and give the LDD time to set up a new Ep0 read; once the 'missing' read
  3038 	was set up either Ep0ReceiveProceed or Ep0ReadSetupPktProceed will be called by the PIL).
  3039 
  3040 	@publishedPartner @released
  3041 */
  3042 TInt DUsbClientController::Ep0RequestComplete(TInt aRealEndpoint, TInt aCount, TInt aError)
  3043 	{
  3044 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::Ep0RequestComplete(%d)", aRealEndpoint));
  3045 
  3046 	// This function may be called by the PSL from within an ISR -- so we have
  3047 	// to take care what we do here (and also in all functions that get called
  3048 	// from here).
  3049 
  3050 	__ASSERT_DEBUG((aRealEndpoint < 2), Kern::Fault(KUsbPILPanicCat, __LINE__));
  3051 	if (aError != KErrNone && aError != KErrPrematureEnd)
  3052 		{
  3053 		__KTRACE_OPT(KUSB, Kern::Printf(" Error: Ep0 request failed (code %d). "
  3054 										"Setting up new Read request.", aError));
  3055 		if (aRealEndpoint == KEp0_Rx)
  3056 			{
  3057 			__KTRACE_OPT(KUSB, Kern::Printf(" (RX request failed)"));
  3058 			StallEndpoint(KEp0_Out);
  3059 			}
  3060 		else
  3061 			{
  3062 			__KTRACE_OPT(KUSB, Kern::Printf(" (TX request failed)"));
  3063 			iEp0WritePending = EFalse;
  3064 			StallEndpoint(KEp0_In);
  3065 			}
  3066 		// our only remedy: set up a new read request
  3067 		SetupEndpointZeroRead();
  3068 		return KErrNone;
  3069 		}
  3070 	TInt r;
  3071 	if (aRealEndpoint & 0x01)
  3072 		{
  3073 		r = ProcessEp0TransmitDone(aCount, aError);
  3074 		}
  3075 	else
  3076 		{
  3077 		r = ProcessEp0ReceiveDone(aCount);
  3078 		if (r == KErrNotFound)
  3079 			{
  3080 			// Don't set up new read yet if data weren't delivered.
  3081 			// (The PSL is supposed, upon encountering this return value,
  3082 			//  to turn off Ep0's interrupt.)
  3083 			return r;
  3084 			}
  3085 		}
  3086 	if (iEp0WritePending == EFalse)
  3087 		{
  3088 		// we're done & no write request has been set up.
  3089 		// so: setup an Ep0 read again
  3090 		__KTRACE_OPT(KUSB, Kern::Printf(" Setting up new Ep0 read request."));
  3091 		SetupEndpointZeroRead();
  3092 		}
  3093 	return r;
  3094 	}
  3095 
  3096 
  3097 /** This function should be called by the PSL once the UDC (and thus the USB device) is in the Address state.
  3098 
  3099 	@publishedPartner @released
  3100 */
  3101 void DUsbClientController::MoveToAddressState()
  3102 	{
  3103 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::MoveToAddressState()"));
  3104 
  3105 	// This function may be called by the PSL from within an ISR -- so we have
  3106 	// to take care what we do here (and also in all functions that get called
  3107 	// from here).
  3108 
  3109 	NextDeviceState(EUsbcDeviceStateAddress);
  3110 	}
  3111 
  3112 
  3113 /** This function should be called by the PSL before certain UDC operations to inform the power model about
  3114 	the electrical current requirements.
  3115 
  3116 	(The exact use of this function is currently not quite clear, so not calling it probably won't harm.)
  3117 
  3118 	@param aCurrent The required electrical current.
  3119 
  3120 	@publishedPartner @released
  3121 */
  3122 void DUsbClientController::SetCurrent(TInt aCurrent)
  3123 	{
  3124 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetCurrent(%d)", aCurrent));
  3125 
  3126 	// Not much for the moment... (What should we do here?)
  3127 	return;
  3128 	}
  3129 
  3130 
  3131 //
  3132 // === Platform Specific Layer (PSL) - private/virtual =============================================
  3133 //
  3134 
  3135 TInt DUsbClientController::OpenDmaChannel(TInt aRealEndpoint)
  3136 	{
  3137 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::OpenDmaChannel(%d)", aRealEndpoint));
  3138 	return KErrNone;
  3139 	}
  3140 
  3141 
  3142 void DUsbClientController::CloseDmaChannel(TInt aRealEndpoint)
  3143 	{
  3144 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CloseDmaChannel(%d)", aRealEndpoint));
  3145 	}
  3146 
  3147 
  3148 TBool DUsbClientController::CableDetectWithoutPowerCaps() const
  3149 	{
  3150 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CableDetectWithoutPowerCaps()"));
  3151 	// Should be overridden in PSL if applicable.
  3152 	return EFalse;
  3153 	}
  3154 
  3155 
  3156 TBool DUsbClientController::DeviceHighSpeedCaps() const
  3157 	{
  3158 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceHighSpeedCaps()"));
  3159 	// Should be overridden in PSL if applicable.
  3160 	return EFalse;
  3161 	}
  3162 
  3163 
  3164 TBool DUsbClientController::DeviceResourceAllocV2Caps() const
  3165 	{
  3166 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceResourceAllocV2Caps()"));
  3167 	// Should be overridden in PSL if applicable.
  3168 	return EFalse;
  3169 	}
  3170 
  3171 
  3172 TBool DUsbClientController::DeviceHnpHandledByHardwareCaps() const
  3173 	{
  3174 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeviceHnpHandledByHardwareCaps()"));
  3175 	// Should be overridden in PSL if applicable.
  3176 	return EFalse;
  3177 	}
  3178 
  3179 
  3180 TInt DUsbClientController::EnterTestMode(TInt aTestSelector)
  3181 	{
  3182 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnterTestMode(%d)", aTestSelector));
  3183 	// Should be overridden in PSL if applicable.
  3184 	return KErrNotSupported;
  3185 	}
  3186 
  3187 
  3188 TBool DUsbClientController::PowerDownWhenActive() const
  3189 	{
  3190  	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerDownWhenActive()"));
  3191  	return EFalse;
  3192 	}
  3193 
  3194 
  3195 TInt DUsbClientController::PowerDown()
  3196 	{
  3197  	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerDown()"));
  3198  	return KErrNone;
  3199 	}
  3200 
  3201 
  3202 TInt DUsbClientController::PowerUp()
  3203 	{
  3204  	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerUp()"));
  3205  	return KErrNone;
  3206 	}
  3207 
  3208 
  3209 TInt DUsbClientController::OtgEnableUdc()
  3210 	{
  3211  	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::OtgEnableUdc()"));
  3212  	return KErrNone;
  3213 	}
  3214 
  3215 
  3216 TInt DUsbClientController::OtgDisableUdc()
  3217    	{
  3218  	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::OtgDisableUdc()"));
  3219  	return KErrNone;
  3220 	}
  3221 
  3222 
  3223 //
  3224 // === USB Controller member function implementations - Internal utility functions (private) =======
  3225 //
  3226 
  3227 TInt DUsbClientController::DeRegisterClientCallback(const DBase* aClientId)
  3228     {
  3229 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterClientCallback()"));
  3230 	__ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__));
  3231 	TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
  3232 	TUsbcClientCallback* p;
  3233 	while ((p = iter++) != NULL)
  3234 		if (p->Owner() == aClientId)
  3235 			{
  3236 			__KTRACE_OPT(KUSB, Kern::Printf("  removing ClientCallback @ 0x%x", p));
  3237 			iClientCallbacks.Remove(*p);
  3238 			return KErrNone;
  3239 			}
  3240 	__KTRACE_OPT(KUSB, Kern::Printf("  Client not found"));
  3241 	return KErrNotFound;
  3242     }
  3243 
  3244 
  3245 TBool DUsbClientController::CheckEpAvailability(TInt aEndpointsUsed,
  3246 												const TUsbcEndpointInfoArray& aEndpointData,
  3247 												TInt aIfcNumber) const
  3248 	{
  3249 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CheckEpAvailability()"));
  3250 	if (aEndpointsUsed > KMaxEndpointsPerClient)
  3251 		{
  3252 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: too many endpoints claimed (%d)", aEndpointsUsed));
  3253 		return EFalse;
  3254 		}
  3255 	TBool reserve[KUsbcEpArraySize]; // iDeviceTotalEndpoints can be equal to 32
  3256 	memset(reserve, EFalse, sizeof(reserve));				// reset the array
  3257 	for (TInt i = 0; i < aEndpointsUsed; ++i)
  3258 		{
  3259 		__KTRACE_OPT(KUSB, Kern::Printf("  checking for (user) endpoint #%d availability...", i + 1));
  3260 		TInt j = 2;
  3261 		while (j < iDeviceTotalEndpoints)
  3262 			{
  3263 			if ((iRealEndpoints[j].EndpointSuitable(&aEndpointData[i], aIfcNumber)) &&
  3264 				(reserve[j] == EFalse))
  3265 				{
  3266 				__KTRACE_OPT(KUSB, Kern::Printf("  ---> found suitable endpoint: RealEndpoint #%d", j));
  3267 				reserve[j] = ETrue;							// found one: mark this ep as reserved
  3268 				break;
  3269 				}
  3270 			__KTRACE_OPT(KUSB, Kern::Printf("  -> endpoint not suitable: RealEndpoint #%d", j));
  3271 			j++;
  3272 			}
  3273 		if (j == iDeviceTotalEndpoints)
  3274 			{
  3275 			return EFalse;
  3276 			}
  3277 		}
  3278 	return ETrue;
  3279 	}
  3280 
  3281 
  3282 TUsbcInterface* DUsbClientController::CreateInterface(const DBase* aClientId, TInt aIfc, TUint32 aFeatureWord)
  3283 // We know that 9.2.3 says: "Interfaces are numbered from zero to one less than the number of
  3284 // concurrent interfaces supported by the configuration."  But since we permit the user to
  3285 // change interface numbers, we can neither assume nor enforce anything about them here.
  3286 	{
  3287 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CreateInterface(x, aIfc=%d)", aIfc));
  3288 	TUsbcInterfaceSet* ifcset_ptr = NULL;
  3289 	TInt ifcset = ClientId2InterfaceNumber(aClientId);
  3290 	TBool new_ifc;
  3291 	if (ifcset < 0)
  3292 		{
  3293 		// New interface(set), so we need to find a number for it.
  3294 		new_ifc = ETrue;
  3295 		const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
  3296 		if (num_ifcsets == 255)
  3297 			{
  3298 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Too many interfaces already exist: 255"));
  3299 			return NULL;
  3300 			}
  3301 		// Find the smallest interface number that has not yet been used.
  3302 		for (ifcset = 0; ifcset < 256; ++ifcset)
  3303 			{
  3304 			TBool n_used = EFalse;
  3305 			for (TInt i = 0; i < num_ifcsets; ++i)
  3306 				{
  3307 				if ((iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber) == ifcset)
  3308 					{
  3309 					__KTRACE_OPT(KUSB, Kern::Printf("  interface number %d already used", ifcset));
  3310 					n_used = ETrue;
  3311 					break;
  3312 					}
  3313 				}
  3314 			if (!n_used)
  3315 				{
  3316 				break;
  3317 				}
  3318 			}
  3319 		if (ifcset == 256)
  3320 			{
  3321 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no available interface number found"));
  3322 			return NULL;
  3323 			}
  3324 		// append the ifcset
  3325 		__KTRACE_OPT(KUSB, Kern::Printf("  creating new InterfaceSet %d first", ifcset));
  3326 		if (aIfc != 0)
  3327 			{
  3328 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface setting number (1): %d", aIfc));
  3329 			return NULL;
  3330 			}
  3331 		if ((ifcset_ptr = new TUsbcInterfaceSet(aClientId, ifcset)) == NULL)
  3332 			{
  3333 			__KTRACE_OPT(KPANIC,
  3334 						 Kern::Printf("  Error: new TUsbcInterfaceSet(aClientId, ifcset_num) failed"));
  3335 			return NULL;
  3336 			}
  3337 		iConfigs[0]->iInterfaceSets.Append(ifcset_ptr);
  3338 		}
  3339 	else /* if (ifcset_num >= 0) */
  3340 		{
  3341 		// use an existent ifcset
  3342 		new_ifc = EFalse;
  3343 		__KTRACE_OPT(KUSB, Kern::Printf("  using existing InterfaceSet %d", ifcset));
  3344 		ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
  3345 		if (aIfc != ifcset_ptr->iInterfaces.Count())
  3346 			{
  3347 			// 9.2.3: "Alternate settings range from zero to one less than the number of alternate
  3348 			// settings for a specific interface." (Thus we can here only append a setting.)
  3349 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface setting number (2): %d", aIfc));
  3350 			return NULL;
  3351 			}
  3352 		// Check whether the existing interface belongs indeed to this client
  3353 		if (ifcset_ptr->iClientId != aClientId)
  3354 			{
  3355 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: iClientId (%p) != aClientId (%p)",
  3356 											  ifcset_ptr->iClientId, aClientId));
  3357 			return NULL;
  3358 			}
  3359 		}
  3360 	const TBool no_ep0_requests = aFeatureWord & KUsbcInterfaceInfo_NoEp0RequestsPlease;
  3361 	TUsbcInterface* const ifc_ptr = new TUsbcInterface(ifcset_ptr, aIfc, no_ep0_requests);
  3362 	if (!ifc_ptr)
  3363 		{
  3364 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: new TUsbcInterface(ifcset, aIfc) failed"));
  3365 		if (new_ifc)
  3366 			{
  3367 			DeleteInterfaceSet(ifcset);
  3368 			}
  3369 		return NULL;
  3370 		}
  3371 	ifcset_ptr->iInterfaces.Append(ifc_ptr);
  3372 	return ifc_ptr;
  3373 	}
  3374 
  3375 
  3376 #define RESET_SETTINGRESERVE \
  3377 	for (TInt i = start_ep; i < iDeviceTotalEndpoints; i++) \
  3378 		{ \
  3379 		if (iRealEndpoints[i].iSettingReserve) \
  3380 			iRealEndpoints[i].iSettingReserve = EFalse; \
  3381 		} \
  3382 
  3383 TInt DUsbClientController::CreateEndpoints(TUsbcInterface* aIfc, TInt aEndpointsUsed,
  3384 										   const TUsbcEndpointInfoArray& aEndpointData,
  3385 										   TInt aRealEpNumbers[])
  3386 	{
  3387 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CreateEndpoints()"));
  3388 	const TInt ifc_num = aIfc->iInterfaceSet->iInterfaceNumber;
  3389 	const TInt start_ep = 2;
  3390 	for (TInt i = 0; i < aEndpointsUsed; ++i)
  3391 		{
  3392 		for (TInt j = start_ep; j < iDeviceTotalEndpoints; ++j)
  3393 			{
  3394 			if (iRealEndpoints[j].EndpointSuitable(&aEndpointData[i], ifc_num))
  3395 				{
  3396 				// Logical endpoints are numbered 1..KMaxEndpointsPerClient (virtual 0 is real 0 and 1)
  3397 				TUsbcLogicalEndpoint* const ep = new TUsbcLogicalEndpoint(this, i + 1, aEndpointData[i],
  3398 																		  aIfc, &iRealEndpoints[j]);
  3399 				if (!ep)
  3400 					{
  3401 					__KTRACE_OPT(KPANIC, Kern::Printf("  Error: new TUsbcLogicalEndpoint() failed"));
  3402 					aIfc->iEndpoints.ResetAndDestroy();
  3403 					RESET_SETTINGRESERVE;
  3404 					return KErrNoMemory;
  3405 					}
  3406 				aIfc->iEndpoints.Append(ep);
  3407 				// Check on logical endpoint's sizes for compliance with special restrictions.
  3408 				if (aIfc->iSettingCode == 0)
  3409 					{
  3410 					// For details see last paragraph of 5.7.3 "Interrupt Transfer Packet Size Constraints".
  3411 					if ((ep->iInfo.iType == KUsbEpTypeInterrupt) && (ep->iEpSize_Hs > 64))
  3412 						{
  3413 						__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: INT ep HS size = %d on default ifc setting",
  3414 														  ep->iEpSize_Hs));
  3415 						__KTRACE_OPT(KPANIC, Kern::Printf("           (should be <= 64)"));
  3416 						}
  3417 					// For details see last paragraph of 5.6.3 "Isochronous Transfer Packet Size Constraints".
  3418 					else if ((ep->iInfo.iType == KUsbEpTypeIsochronous) && (ep->iInfo.iSize > 0))
  3419 						{
  3420 						__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: ISO ep size = %d on default ifc setting",
  3421 														  ep->iInfo.iSize));
  3422 						__KTRACE_OPT(KPANIC, Kern::Printf("           (should be zero or ep non-existent)"));
  3423 						}
  3424 					}
  3425 				// If the endpoint doesn't support DMA (now or never) the next operation
  3426 				// will be a successful no-op.
  3427 				const TInt r = OpenDmaChannel(j);
  3428 				if (r != KErrNone)
  3429 					{
  3430 					__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Opening of DMA channel failed"));
  3431 					aIfc->iEndpoints.ResetAndDestroy();
  3432 					RESET_SETTINGRESERVE;
  3433 					return r;
  3434 					}
  3435 				__KTRACE_OPT(KUSB, Kern::Printf("  creating ep: mapping real ep %d -> logical ep %d",
  3436 												j, i + 1));
  3437 				iRealEndpoints[j].iIfcNumber = &aIfc->iInterfaceSet->iInterfaceNumber;
  3438 				iRealEndpoints[j].iSettingReserve = ETrue;
  3439 				__KTRACE_OPT(KUSB,
  3440 							 Kern::Printf("  ep->iInfo: iType=0x%x iDir=0x%x iSize=%d iInterval=%d",
  3441 										  ep->iInfo.iType, ep->iInfo.iDir, ep->iInfo.iSize,
  3442 										  ep->iInfo.iInterval));
  3443 				__KTRACE_OPT(KUSB,
  3444 							 Kern::Printf("  ep->iInfo: iInterval_Hs=%d iTransactions=%d iExtra=%d",
  3445 										  ep->iInfo.iInterval_Hs, ep->iInfo.iTransactions,
  3446 										  ep->iInfo.iExtra));
  3447 				// Store real endpoint numbers:
  3448 				// array[x] holds the number for logical ep x.
  3449 				aRealEpNumbers[i + 1] = j;
  3450 				break;
  3451 				}
  3452 			}
  3453 		}
  3454 	aRealEpNumbers[0] = 0;								// ep0: 0.
  3455 	__KTRACE_OPT(KUSB,{
  3456 		Kern::Printf("  Endpoint Mapping for Interface %d / Setting %d:", ifc_num, aIfc->iSettingCode);
  3457 		Kern::Printf("Logical  | Real");
  3458 		Kern::Printf("Endpoint | Endpoint");
  3459 		for (TInt ep = 0; ep <= aEndpointsUsed; ++ep) Kern::Printf("   %2d       %3d",ep, aRealEpNumbers[ep]);
  3460 		});
  3461 	RESET_SETTINGRESERVE;
  3462 	return KErrNone;
  3463 	}
  3464 
  3465 
  3466 TInt DUsbClientController::SetupIfcDescriptor(TUsbcInterface* aIfc, TUsbcClassInfo& aClass, DThread* aThread,
  3467 											  TDesC8* aString, const TUsbcEndpointInfoArray& aEndpointData)
  3468 	{
  3469 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetupIfcDescriptor()"));
  3470 
  3471 	// Interface descriptor
  3472 	TUsbcDescriptorBase* d = TUsbcInterfaceDescriptor::New(aIfc->iInterfaceSet->iInterfaceNumber,
  3473 														   aIfc->iSettingCode,
  3474 														   aIfc->iEndpoints.Count(),
  3475 														   aClass);
  3476 	if (!d)
  3477 		{
  3478 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ifc desc failed."));
  3479 		return KErrNoMemory;
  3480 		}
  3481 	iDescriptors.InsertDescriptor(d);
  3482 
  3483 	// Interface string descriptor
  3484 	if (aString)
  3485 		{
  3486 		// we don't know the length of the string, so we have to allocate memory dynamically
  3487 		TUint strlen = Kern::ThreadGetDesLength(aThread, aString);
  3488 		if (strlen > KUsbStringDescStringMaxSize)
  3489 			{
  3490 			__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: $ descriptor too long - string will be truncated"));
  3491 			strlen = KUsbStringDescStringMaxSize;
  3492 			}
  3493 		HBuf8* const stringbuf = HBuf8::New(strlen);
  3494 		if (!stringbuf)
  3495 			{
  3496 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ifc $ desc string failed."));
  3497 			iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
  3498 											 aIfc->iSettingCode);
  3499 			return KErrNoMemory;
  3500 			}
  3501 		stringbuf->SetMax();
  3502 		// the aString points to data that lives in user memory, so we have to copy it:
  3503 		TInt r = Kern::ThreadDesRead(aThread, aString, *stringbuf, 0);
  3504 		if (r != KErrNone)
  3505 			{
  3506 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Thread read error"));
  3507 			iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
  3508 											 aIfc->iSettingCode);
  3509 			delete stringbuf;
  3510 			return r;
  3511 			}
  3512 		TUsbcStringDescriptor* const sd = TUsbcStringDescriptor::New(*stringbuf);
  3513 		if (!sd)
  3514 			{
  3515 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ifc $ desc failed."));
  3516 			iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
  3517 											 aIfc->iSettingCode);
  3518 			delete stringbuf;
  3519 			return KErrNoMemory;
  3520 			}
  3521 		iDescriptors.SetIfcStringDescriptor(sd, aIfc->iInterfaceSet->iInterfaceNumber, aIfc->iSettingCode);
  3522 		delete stringbuf;									// the (EPOC) descriptor was copied by New()
  3523 		}
  3524 
  3525 	// Endpoint descriptors
  3526 	for (TInt i = 0; i < aIfc->iEndpoints.Count(); ++i)
  3527 		{
  3528 		// The reason for using another function argument for Endpoint Info
  3529 		// (and not possibly - similar to the Endpoint Address -
  3530 		// "aIfc->iEndpoints[i]->iPEndpoint->iLEndpoint->iInfo") is that this time
  3531 		// there are no logical endpoints associated with our real endpoints,
  3532 		// i.e. iLEndpoint is NULL!.
  3533 		if (aEndpointData[i].iExtra)
  3534 			{
  3535 			// if a non-standard endpoint descriptor is requested...
  3536 			if (aEndpointData[i].iExtra != 2)
  3537 				{
  3538 				// ...then it must be a Audio Class endpoint descriptor. Else...
  3539 				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: EP desc extension > 2 bytes (%d)",
  3540 												  aEndpointData[i].iExtra));
  3541 				iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
  3542 												 aIfc->iSettingCode);
  3543 				return KErrArgument;
  3544 				}
  3545 			d = TUsbcAudioEndpointDescriptor::New(aIfc->iEndpoints[i]->iPEndpoint->iEndpointAddr,
  3546 												  aEndpointData[i]);
  3547 			}
  3548 		else
  3549 			{
  3550 			d = TUsbcEndpointDescriptor::New(aIfc->iEndpoints[i]->iPEndpoint->iEndpointAddr,
  3551 											 aEndpointData[i]);
  3552 			}
  3553 		if (!d)
  3554 			{
  3555 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for ep desc #%d failed.", i));
  3556 			iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber,
  3557 											 aIfc->iSettingCode);
  3558 			return KErrNoMemory;
  3559 			}
  3560 		iDescriptors.InsertDescriptor(d);
  3561 		}
  3562 
  3563 	return KErrNone;
  3564 	}
  3565 
  3566 
  3567 TInt DUsbClientController::ClientId2InterfaceNumber(const DBase* aClientId) const
  3568 	{
  3569 	const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
  3570 	for (TInt i = 0; i < num_ifcsets; ++i)
  3571 		{
  3572 		if (iConfigs[0]->iInterfaceSets[i]->iClientId == aClientId)
  3573 			{
  3574 			return iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber;
  3575 			}
  3576 		}
  3577 	return -1;
  3578 	}
  3579 
  3580 
  3581 TUsbcInterfaceSet* DUsbClientController::ClientId2InterfacePointer(const DBase* aClientId) const
  3582 	{
  3583 	const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
  3584 	for (TInt i = 0; i < num_ifcsets; ++i)
  3585 		{
  3586 		if (iConfigs[0]->iInterfaceSets[i]->iClientId == aClientId)
  3587 			{
  3588 			return iConfigs[0]->iInterfaceSets[i];
  3589 			}
  3590 		}
  3591 	return NULL;
  3592 	}
  3593 
  3594 
  3595 const DBase* DUsbClientController::InterfaceNumber2ClientId(TInt aIfcSet) const
  3596 	{
  3597 	if (!InterfaceExists(aIfcSet))
  3598 		{
  3599 		return NULL;
  3600 		}
  3601 	return InterfaceNumber2InterfacePointer(aIfcSet)->iClientId;
  3602 	}
  3603 
  3604 
  3605 TUsbcInterfaceSet* DUsbClientController::InterfaceNumber2InterfacePointer(TInt aIfcSet) const
  3606 	{
  3607 	const TInt num_ifcsets = iConfigs[0]->iInterfaceSets.Count();
  3608 	for (TInt i = 0; i < num_ifcsets; ++i)
  3609 		{
  3610 		if ((iConfigs[0]->iInterfaceSets[i]->iInterfaceNumber) == aIfcSet)
  3611 			{
  3612 			return iConfigs[0]->iInterfaceSets[i];
  3613 			}
  3614 		}
  3615 	return NULL;
  3616 	}
  3617 
  3618 
  3619 TInt DUsbClientController::ActivateHardwareController()
  3620 	{
  3621 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ActivateHardwareController()"));
  3622 	if (iHardwareActivated)
  3623 		{
  3624 		__KTRACE_OPT(KUSB, Kern::Printf("  already active -> returning"));
  3625 		return KErrNone;
  3626 		}
  3627 	// Initialise HW
  3628 	TInt r = StartUdc();
  3629 	if (r != KErrNone)
  3630 		{
  3631 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: StartUdc() failed"));
  3632 		return KErrHardwareNotAvailable;
  3633 		}
  3634 	r = OtgEnableUdc();							   // turn on UDC (OTG flavour)
  3635 	if (r != KErrNone)
  3636 		{
  3637 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: OtgEnableUdc() failed: %d", r));
  3638 		}
  3639 	iHardwareActivated = ETrue;
  3640 
  3641 	// Configure & enable endpoint zero
  3642 	const TUsbcLogicalEndpoint* const ep0_0 = iRealEndpoints[0].iLEndpoint;
  3643 	const TUsbcLogicalEndpoint* const ep0_1 = iRealEndpoints[1].iLEndpoint;
  3644 	if (iHighSpeed)
  3645 		{
  3646 		const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Hs;
  3647 		const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Hs;
  3648 		}
  3649 	else
  3650 		{
  3651 		const_cast<TUsbcLogicalEndpoint*>(ep0_0)->iInfo.iSize = ep0_0->iEpSize_Fs;
  3652 		const_cast<TUsbcLogicalEndpoint*>(ep0_1)->iInfo.iSize = ep0_1->iEpSize_Fs;
  3653 		}
  3654 	ConfigureEndpoint(0, ep0_0->iInfo);
  3655 	ConfigureEndpoint(1, ep0_1->iInfo);
  3656 	iEp0MaxPacketSize = ep0_0->iInfo.iSize;
  3657 
  3658 	__KTRACE_OPT(KUSB, Kern::Printf("  Controller activated."));
  3659 	if (UsbConnectionStatus())
  3660 		{
  3661 		if (iDeviceState == EUsbcDeviceStateUndefined)
  3662 			{
  3663 			NextDeviceState(EUsbcDeviceStateAttached);
  3664 			}
  3665 		NextDeviceState(EUsbcDeviceStatePowered);
  3666 		}
  3667 	return  KErrNone;;
  3668 	}
  3669 
  3670 
  3671 void DUsbClientController::DeActivateHardwareController()
  3672 	{
  3673 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeActivateHardwareController()"));
  3674 	if (!iHardwareActivated)
  3675 		{
  3676 		__KTRACE_OPT(KUSB, Kern::Printf("  not active -> returning"));
  3677 		return;
  3678 		}
  3679 	// Deconfigure & disable endpoint zero
  3680 	DeConfigureEndpoint(KEp0_Out);
  3681 	DeConfigureEndpoint(KEp0_In);
  3682 	// Stop HW
  3683 	TInt r = OtgDisableUdc();					  // turn off UDC (OTG flavour)
  3684 	if (r != KErrNone)
  3685 		{
  3686 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: OtgDisableUdc() failed: %d", r));
  3687 		}
  3688 	StopUdc();
  3689 	iHardwareActivated = EFalse;
  3690 	__KTRACE_OPT(KUSB, Kern::Printf("  Controller deactivated."));
  3691 	if (UsbConnectionStatus())
  3692 		{
  3693 		NextDeviceState(EUsbcDeviceStateAttached);
  3694 		}
  3695 	return;
  3696 	}
  3697 
  3698 
  3699 void DUsbClientController::DeleteInterfaceSet(TInt aIfcSet)
  3700 	{
  3701 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteInterfaceSet(%d)", aIfcSet));
  3702 	TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(aIfcSet);
  3703 	if (!ifcset_ptr)
  3704 		{
  3705 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface number: %d", aIfcSet));
  3706 		return;
  3707 		}
  3708 	const TInt idx = iConfigs[0]->iInterfaceSets.Find(ifcset_ptr);
  3709 	if (idx == KErrNotFound)
  3710 		{
  3711 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: interface not found in array"));
  3712 		return;
  3713 		}
  3714 	iConfigs[0]->iInterfaceSets.Remove(idx);
  3715 	delete ifcset_ptr;
  3716 	}
  3717 
  3718 
  3719 void DUsbClientController::DeleteInterface(TInt aIfcSet, TInt aIfc)
  3720 	{
  3721 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteInterface(%d, %d)", aIfcSet, aIfc));
  3722 	TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(aIfcSet);
  3723 	if (!ifcset_ptr)
  3724 		{
  3725 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface number: %d", aIfcSet));
  3726 		return;
  3727 		}
  3728 	if (ifcset_ptr->iInterfaces.Count() <= aIfc)
  3729 		{
  3730 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid interface setting: %d", aIfc));
  3731 		return;
  3732 		}
  3733 	TUsbcInterface* const ifc_ptr = ifcset_ptr->iInterfaces[aIfc];
  3734 	// Always first remove, then delete (see ~TUsbcLogicalEndpoint() for the reason why)
  3735 	ifcset_ptr->iInterfaces.Remove(aIfc);
  3736 	delete ifc_ptr;
  3737 	if (aIfc == ifcset_ptr->iCurrentInterface)
  3738 		{
  3739 		__KTRACE_OPT(KUSB, Kern::Printf(" > Warning: deleting current interface setting"));
  3740 		ifcset_ptr->iCurrentInterface = 0;
  3741 		}
  3742 	}
  3743 
  3744 
  3745 void DUsbClientController::CancelTransferRequests(TInt aRealEndpoint)
  3746 	{
  3747 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CancelTransferRequests(aRealEndpoint=%d)",
  3748 									aRealEndpoint));
  3749 	const DBase* const clientId = PEndpoint2ClientId(aRealEndpoint);
  3750 	if (EpIdx2Addr(aRealEndpoint) & KUsbEpAddress_In)
  3751 		{
  3752 		CancelWriteBuffer(clientId, aRealEndpoint);
  3753 		}
  3754 	else
  3755 		{
  3756 		CancelReadBuffer(clientId, aRealEndpoint);
  3757 		}
  3758 	}
  3759 
  3760 
  3761 void DUsbClientController::DeleteRequestCallback(const DBase* aClientId, TInt aEndpointNum,
  3762 												 TTransferDirection aTransferDir)
  3763 	{
  3764 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallback()"));
  3765 	// Ep0 OUT
  3766 	if (aEndpointNum == 0)
  3767 		{
  3768 		const TInt irq = NKern::DisableAllInterrupts();
  3769 		TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
  3770 		TUsbcRequestCallback* p;
  3771 		while ((p = iter++) != NULL)
  3772 			{
  3773 			if (p->Owner() == aClientId)
  3774 				{
  3775 				__ASSERT_DEBUG((p->iRealEpNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
  3776 				__ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__));
  3777 				__KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x (ep0)", p));
  3778 				iEp0ReadRequestCallbacks.Remove(*p);
  3779 				}
  3780 			}
  3781 		NKern::RestoreInterrupts(irq);
  3782 		return;
  3783 		}
  3784 	// Other endpoints
  3785 	TUsbcRequestCallback* const p = iRequestCallbacks[aEndpointNum];
  3786 	if (p)
  3787 		{
  3788  		__ASSERT_DEBUG((p->Owner() == aClientId), Kern::Fault(KUsbPILPanicCat, __LINE__));
  3789 		__ASSERT_DEBUG((p->iTransferDir == aTransferDir), Kern::Fault(KUsbPILPanicCat, __LINE__));
  3790 		__KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x", p));
  3791 		iRequestCallbacks[aEndpointNum] = NULL;
  3792 		}
  3793 	}
  3794 
  3795 
  3796 void DUsbClientController::DeleteRequestCallbacks(const DBase* aClientId)
  3797 	{
  3798 	// aClientId being NULL means: delete all requests for *all* clients.
  3799 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallbacks()"));
  3800 	// Ep0 OUT
  3801 	const TInt irq = NKern::DisableAllInterrupts();
  3802 	TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
  3803 	TUsbcRequestCallback* p;
  3804 	while ((p = iter++) != NULL)
  3805 		{
  3806 		if (!aClientId || p->Owner() == aClientId)
  3807 			{
  3808 			__KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x (ep0)", p));
  3809 			iEp0ReadRequestCallbacks.Remove(*p);
  3810 			}
  3811 		}
  3812 	NKern::RestoreInterrupts(irq);
  3813 	// Other endpoints
  3814 	for (TInt i = 1; i < KUsbcEpArraySize; i++)
  3815 		{
  3816 		TUsbcRequestCallback* const p = iRequestCallbacks[i];
  3817 		if (p && (!aClientId || p->Owner() == aClientId))
  3818 			{
  3819 			__KTRACE_OPT(KUSB, Kern::Printf("  removing RequestCallback @ 0x%x", p));
  3820 			iRequestCallbacks[i] = NULL;
  3821 			}
  3822 		}
  3823 	}
  3824 
  3825 
  3826 void DUsbClientController::StatusNotify(TUsbcDeviceState aState, const DBase* aClientId)
  3827 	{
  3828 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::StatusNotify()"));
  3829 
  3830 	// This function may be called by the PSL (via chapter9.cpp) from within an
  3831 	// ISR -- so we have to take care what we do here (and also in all
  3832 	// functions that get called from here).
  3833 
  3834 	TSglQueIter<TUsbcStatusCallback> iter(iStatusCallbacks);
  3835 	TUsbcStatusCallback* p;
  3836 	while ((p = iter++) != NULL)
  3837 		{
  3838 		if (!aClientId || aClientId == p->Owner())
  3839 			{
  3840 			__KTRACE_OPT(KUSB, Kern::Printf("  notifying LDD @ 0x%x about %d", p->Owner(), aState));
  3841 			p->SetState(aState);
  3842 			p->DoCallback();
  3843 			}
  3844 		}
  3845 	}
  3846 
  3847 
  3848 void DUsbClientController::EpStatusNotify(TInt aRealEndpoint)
  3849 	{
  3850 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EpStatusNotify()"));
  3851 
  3852 	// This function may be called by the PSL (via chapter9.cpp) from within an
  3853 	// ISR -- so we have to take care what we do here (and also in all
  3854 	// functions that get called from here).
  3855 
  3856 	const DBase* const client_id = PEndpoint2ClientId(aRealEndpoint);
  3857 	if (!client_id)
  3858 		{
  3859 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Client not found for real ep %d", aRealEndpoint));
  3860 		return;
  3861 		}
  3862 	// Check if there is a notification request queued for that client (if not, we can return here).
  3863 	TSglQueIter<TUsbcEndpointStatusCallback> iter(iEpStatusCallbacks);
  3864 	TUsbcEndpointStatusCallback* p;
  3865 	while ((p = iter++) != NULL)
  3866 		{
  3867 		if (p->Owner() == client_id)
  3868 			{
  3869 			break;
  3870 			}
  3871 		}
  3872 	if (!p)
  3873 		{
  3874 		__KTRACE_OPT(KUSB, Kern::Printf("  No notification request for that client, returning"));
  3875 		return;
  3876 		}
  3877 	const TInt ifcset = ClientId2InterfaceNumber(client_id);
  3878 	if (ifcset < 0)
  3879 		{
  3880 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ifcset not found for clientid %d", client_id));
  3881 		return;
  3882 		}
  3883 	const TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(ifcset);
  3884 	if (!ifcset_ptr)
  3885 		{
  3886 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ifcset pointer not found for ifcset %d", ifcset));
  3887 		return;
  3888 		}
  3889 	const TUsbcInterface* const ifc_ptr = ifcset_ptr->CurrentInterface();
  3890 	if (!ifc_ptr)
  3891 		{
  3892 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Current ifc pointer not found for ifcset %d", ifcset));
  3893 		return;
  3894 		}
  3895 	TUint state = 0;
  3896 	const TInt eps = ifc_ptr->iEndpoints.Count();
  3897 	for (TInt i = 0; i < eps; i++)
  3898 		{
  3899 		const TUsbcLogicalEndpoint* const ep_ptr = ifc_ptr->iEndpoints[i];
  3900 		__KTRACE_OPT(KUSB, Kern::Printf("  checking logical ep #%d for stall state...",
  3901 										ep_ptr->iLEndpointNum));
  3902 		if (ep_ptr->iPEndpoint->iHalt)
  3903 			{
  3904 			__KTRACE_OPT(KUSB, Kern::Printf("  -- stalled"));
  3905 			// set the bit n to 1, where n is the logical endpoint number minus one
  3906 			state |= (1 << (ep_ptr->iLEndpointNum - 1));
  3907 			}
  3908 		else
  3909 			{
  3910 			__KTRACE_OPT(KUSB, Kern::Printf("  -- not stalled"));
  3911 			}
  3912 		}
  3913 	__KTRACE_OPT(KUSB, Kern::Printf(" passing ep state 0x%x on to LDD @ 0x%x", state, client_id));
  3914 	p->SetState(state);
  3915 	p->DoCallback();
  3916 	}
  3917 
  3918 
  3919 void DUsbClientController::OtgFeaturesNotify()
  3920 	{
  3921 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::OtgFeaturesNotify()"));
  3922 
  3923 	// This function may be called from the PSL (via PIL's chapter9.cpp) from
  3924 	// within an ISR -- so we have to take care what we do here (and also in
  3925 	// all functions that get called from here).
  3926 
  3927 	TSglQueIter<TUsbcOtgFeatureCallback> iter(iOtgCallbacks);
  3928 	TUsbcOtgFeatureCallback* p;
  3929 	while ((p = iter++) != NULL)
  3930 		{
  3931 		p->SetFeatures(iOtgFuncMap & 0x1C);
  3932 		p->DoCallback();
  3933 		}
  3934 	}
  3935 
  3936 
  3937 void DUsbClientController::RunClientCallbacks()
  3938 	{
  3939 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::RunClientCallbacks()"));
  3940 	TSglQueIter<TUsbcClientCallback> iter(iClientCallbacks);
  3941 	TUsbcClientCallback* p;
  3942 	while ((p = iter++) != NULL)
  3943 		{
  3944 		__KTRACE_OPT(KUSB, Kern::Printf("Callback 0x%x", p));
  3945 		p->DoCallback();
  3946 		}
  3947 	}
  3948 
  3949 
  3950 void DUsbClientController::ProcessDataTransferDone(TUsbcRequestCallback& aRcb)
  3951 	{
  3952 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessDataTransferDone()"));
  3953 	// This piece can only be called in thread context from ProcessEp0DataReceived() /
  3954 	// ProcessEp0SetupReceived() via the call to ProcessEp0ReceiveDone() in
  3955 	// SetupReadBuffer(), which is guarded by an interrupt lock.
  3956 	TInt ep = aRcb.iRealEpNum;
  3957 	if (ep == 0)
  3958 		{
  3959 		if (aRcb.iTransferDir == EControllerRead)
  3960 			{
  3961 			// Ep0 OUT is special
  3962 			iEp0ReadRequestCallbacks.Remove(aRcb);
  3963 			}
  3964 		else												// EControllerWrite
  3965 			{
  3966 			// Ep0 IN needs to be adjusted: it's '1' within the PIL.
  3967 			ep = KEp0_Tx;
  3968 			}
  3969 		}
  3970 	if (ep > 0)												// not 'else'!
  3971 		{
  3972 		__ASSERT_DEBUG((iRequestCallbacks[ep] == &aRcb), Kern::Fault(KUsbPILPanicCat, __LINE__));
  3973 		__KTRACE_OPT(KUSB, Kern::Printf(" > removing RequestCallback[%d] @ 0x%x", ep, &aRcb));
  3974 		iRequestCallbacks[ep] = NULL;
  3975 		}
  3976 	aRcb.DoCallback();
  3977 	}
  3978 
  3979 
  3980 void DUsbClientController::NextDeviceState(TUsbcDeviceState aNextState)
  3981 	{
  3982 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::NextDeviceState()"));
  3983 #ifdef _DEBUG
  3984 	const char* const states[] = {"Undefined", "Attached", "Powered", "Default",
  3985 								  "Address", "Configured", "Suspended"};
  3986 	if ((aNextState >= EUsbcDeviceStateUndefined) &&
  3987 		(aNextState <= EUsbcDeviceStateSuspended))
  3988 		{
  3989 		__KTRACE_OPT(KUSB, Kern::Printf("  next device state: %s", states[aNextState]));
  3990 		}
  3991 	else
  3992 		{
  3993 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown next device state: %d", aNextState));
  3994 		}
  3995 	// Print a warning when an invalid state transition is detected
  3996 	// 'Undefined' is not a state that is mentioned in the USB spec, but
  3997 	// that's what we're in once the cable gets pulled (for instance).
  3998 	switch (iDeviceState)
  3999 		{
  4000 	case EUsbcDeviceStateUndefined:
  4001 		// valid: Undefined -> Attached
  4002 		if (aNextState != EUsbcDeviceStateAttached)
  4003 			break;
  4004 		goto OK;
  4005 	case EUsbcDeviceStateAttached:
  4006 		// valid: Attached -> {Undefined, Powered}
  4007 		if ((aNextState != EUsbcDeviceStateUndefined) &&
  4008 			(aNextState != EUsbcDeviceStatePowered))
  4009 			break;
  4010 		goto OK;
  4011 	case EUsbcDeviceStatePowered:
  4012 		// valid: Powered -> {Undefined, Attached, Default, Suspended}
  4013 		if ((aNextState != EUsbcDeviceStateUndefined) &&
  4014 			(aNextState != EUsbcDeviceStateAttached) &&
  4015 			(aNextState != EUsbcDeviceStateDefault)	 &&
  4016 			(aNextState != EUsbcDeviceStateSuspended))
  4017 			break;
  4018 		goto OK;
  4019 	case EUsbcDeviceStateDefault:
  4020 		// valid: Default -> {Undefined, Powered, Default, Address, Suspended}
  4021 		if ((aNextState != EUsbcDeviceStateUndefined) &&
  4022 			(aNextState != EUsbcDeviceStatePowered) &&
  4023 			(aNextState != EUsbcDeviceStateDefault) &&
  4024 			(aNextState != EUsbcDeviceStateAddress) &&
  4025 			(aNextState != EUsbcDeviceStateSuspended))
  4026 			break;
  4027 		goto OK;
  4028 	case EUsbcDeviceStateAddress:
  4029 		// valid: Address -> {Undefined, Powered, Default, Configured, Suspended}
  4030 		if ((aNextState != EUsbcDeviceStateUndefined) &&
  4031 			(aNextState != EUsbcDeviceStatePowered) &&
  4032 			(aNextState != EUsbcDeviceStateDefault) &&
  4033 			(aNextState != EUsbcDeviceStateConfigured) &&
  4034 			(aNextState != EUsbcDeviceStateSuspended))
  4035 			break;
  4036 		goto OK;
  4037 	case EUsbcDeviceStateConfigured:
  4038 		// valid: Configured -> {Undefined, Powered, Default, Address, Suspended}
  4039 		if ((aNextState != EUsbcDeviceStateUndefined) &&
  4040 			(aNextState != EUsbcDeviceStatePowered) &&
  4041 			(aNextState != EUsbcDeviceStateDefault) &&
  4042 			(aNextState != EUsbcDeviceStateAddress) &&
  4043 			(aNextState != EUsbcDeviceStateSuspended))
  4044 			break;
  4045 		goto OK;
  4046 	case EUsbcDeviceStateSuspended:
  4047 		// valid: Suspended -> {Undefined, Powered, Default, Address, Configured}
  4048 		if ((aNextState != EUsbcDeviceStateUndefined) &&
  4049 			(aNextState != EUsbcDeviceStatePowered) &&
  4050 			(aNextState != EUsbcDeviceStateDefault) &&
  4051 			(aNextState != EUsbcDeviceStateAddress) &&
  4052 			(aNextState != EUsbcDeviceStateConfigured))
  4053 			break;
  4054 		goto OK;
  4055 	default:
  4056 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown current device state: %d", iDeviceState));
  4057 		goto OK;
  4058 		}
  4059 	// KUSB only (instead of KPANIC) so as not to worry people too much where
  4060 	// a particular h/w regularly enforces invalid (but harmless) transitions
  4061 	__KTRACE_OPT(KUSB, Kern::Printf("  Warning: Invalid next state from %s", states[iDeviceState]));
  4062 OK:
  4063 #endif // _DEBUG
  4064 
  4065 	iDeviceState = aNextState;
  4066 	StatusNotify(iDeviceState);
  4067 	}
  4068 
  4069 
  4070 TInt DUsbClientController::ProcessSuspendEvent()
  4071 	{
  4072 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSuspendEvent()"));
  4073 	// A suspend interrupt has been received and needs attention.
  4074 	iDeviceStateB4Suspend = iDeviceState;
  4075 	// We have to move to the Suspend state immediately (in case it's a genuine Suspend)
  4076 	// because 7.1.7.6 says: "The device must actually be suspended, [...] after no more
  4077 	// than 10ms of bus inactivity [...]." Assuming we got the interrupt 3ms after the
  4078 	// Suspend condition arose, we have now 7ms left.
  4079 	NextDeviceState(EUsbcDeviceStateSuspended);
  4080 	Suspend();
  4081 	// For some reason we get this interrupt also when the USB cable has been pulled.
  4082 	// So we want to see if that is the case in order to move to the Undefined state instead.
  4083 	// However, instead of immediately checking the status of the USB cable we wait for a
  4084 	// short moment (KUsbCableStatusDelay, see top of file), until things have become stable.
  4085 	// Then, in the timer callback, we can change the device state once more if necessary.
  4086 	iCableStatusTimer.OneShot(KUsbCableStatusDelay);
  4087 	return KErrNone;
  4088 	}
  4089 
  4090 
  4091 //
  4092 // ISR (from CableStatusTimerCallback)
  4093 //
  4094 TInt DUsbClientController::ProcessSuspendEventProceed()
  4095 	{
  4096 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSuspendEventProceed()"));
  4097 	if (!UsbConnectionStatus())
  4098 		{
  4099 		// If we are no longer connected to the bus, we go into Undefined state (from Suspend).
  4100 		__KTRACE_OPT(KUSB, Kern::Printf(" > USB cable detached"));
  4101 		NextDeviceState(EUsbcDeviceStateUndefined);
  4102 		}
  4103 	return KErrNone;
  4104 	}
  4105 
  4106 
  4107 TInt DUsbClientController::ProcessResumeEvent()
  4108 	{
  4109 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessResumeEvent()"));
  4110 	iCableStatusTimer.Cancel();
  4111 	if (iDeviceState == EUsbcDeviceStateSuspended)
  4112 		{
  4113 		NextDeviceState(iDeviceStateB4Suspend);
  4114 		}
  4115 	Resume();
  4116 	return KErrNone;
  4117 	}
  4118 
  4119 
  4120 TInt DUsbClientController::ProcessResetEvent(TBool aPslUpcall)
  4121 	{
  4122 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessResetEvent()"));
  4123 
  4124 	if (aPslUpcall)
  4125 		{
  4126 		// Call back into PSL if we're coming from there.
  4127 		// Also, do it always, even when PIL processing will be deferred.
  4128 		Reset();
  4129 		}
  4130 
  4131 #ifdef USB_OTG_CLIENT
  4132 	if (iUsbResetDeferred) // implies (iOtgHnpHandledByHw == ETrue)
  4133 		{
  4134 		__KTRACE_OPT(KUSB, Kern::Printf("  User-side (still) not ready -> returning"));
  4135 		return KErrNone;
  4136 		}
  4137 	else if (iOtgHnpHandledByHw && !iClientSupportReady)
  4138 		{
  4139 		// Wait with the PIL Reset processing until user-side is ready
  4140 		__KTRACE_OPT(KUSB, Kern::Printf("  User-side not ready -> deferring"));
  4141 		iUsbResetDeferred = ETrue;
  4142 		return KErrNone;
  4143 		}
  4144 #endif // USB_OTG_CLIENT
  4145 
  4146 	iCableStatusTimer.Cancel();
  4147 	if (iDeviceState == EUsbcDeviceStateAttached)
  4148 		{
  4149 		NextDeviceState(EUsbcDeviceStatePowered);
  4150 		}
  4151 	// Notify the world. (This will just queue a DFC, so users won't actually be
  4152 	// notified before we return. But we change the device state already here so
  4153 	// ChangeConfiguration will see the correct one.)
  4154 	NextDeviceState(EUsbcDeviceStateDefault);
  4155 	// Tear down the current configuration (never called from thread)
  4156 	ChangeConfiguration(0);
  4157 	// Reset essential vars
  4158 	iRmWakeupStatus_Enabled = EFalse;
  4159 	ResetEp0DataOutVars();
  4160 	iEp0_RxExtraData = EFalse;
  4161 	iEp0WritePending = EFalse;
  4162 	iEp0ClientDataTransmitting = EFalse;
  4163 	// Reset OTG features, leave attributes as is
  4164 	iOtgFuncMap &= KUsbOtgAttr_SrpSupp | KUsbOtgAttr_HnpSupp;
  4165 	if (iOtgSupport)
  4166 		{
  4167 		OtgFeaturesNotify();
  4168 		}
  4169 
  4170 	// Check whether there's a speed change
  4171 	const TBool was_hs = iHighSpeed;
  4172 	iHighSpeed = CurrentlyUsingHighSpeed();
  4173 	if (!was_hs && iHighSpeed)
  4174 		{
  4175 		__KTRACE_OPT(KUSB, Kern::Printf("  Moving to High-speed"));
  4176 		EnterHighSpeed();
  4177 		}
  4178 	else if (was_hs && !iHighSpeed)
  4179 		{
  4180 		__KTRACE_OPT(KUSB, Kern::Printf("  Moving to Full-speed"));
  4181 		EnterFullSpeed();
  4182 		}
  4183 
  4184 	// Setup initial Ep0 read (SetupEndpointZeroRead never called from thread)
  4185 	if (SetupEndpointZeroRead() != KErrNone)
  4186 		{
  4187 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: while setting up Ep0 read"));
  4188 		return KErrGeneral;
  4189 		}
  4190 
  4191 	return KErrNone;
  4192 	}
  4193 
  4194 
  4195 TInt DUsbClientController::ProcessCableInsertEvent()
  4196 	{
  4197 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessCableInsertEvent()"));
  4198 #ifdef USB_OTG_CLIENT
  4199 	__KTRACE_OPT(KPANIC, Kern::Printf("  Error: EUsbEventCableInsert shouldn't be sent by an OTG Client PSL"));
  4200 	return KErrArgument;
  4201 #else
  4202 	NextDeviceState(EUsbcDeviceStateAttached);
  4203 	if (iHardwareActivated)
  4204 		{
  4205 		NextDeviceState(EUsbcDeviceStatePowered);
  4206 		}
  4207 	return KErrNone;
  4208 #endif	// #ifdef USB_OTG_CLIENT
  4209 	}
  4210 
  4211 
  4212 TInt DUsbClientController::ProcessCableRemoveEvent()
  4213 	{
  4214 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessCableRemoveEvent()"));
  4215 #ifdef USB_OTG_CLIENT
  4216 	__KTRACE_OPT(KPANIC, Kern::Printf("  Error: EUsbEventCableRemoved shouldn't be sent by an OTG Client PSL"));
  4217 	return KErrArgument;
  4218 #else
  4219 	// Tear down the current configuration (if any)
  4220 	ChangeConfiguration(0);
  4221 	NextDeviceState(EUsbcDeviceStateUndefined);
  4222 	return KErrNone;
  4223 #endif	// #ifdef USB_OTG_CLIENT
  4224 	}
  4225 
  4226 
  4227 void DUsbClientController::EnterFullSpeed()
  4228 	{
  4229 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnterFullSpeed()"));
  4230 	iDescriptors.UpdateDescriptorsFs();
  4231 	}
  4232 
  4233 
  4234 void DUsbClientController::EnterHighSpeed()
  4235 	{
  4236 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnterHighSpeed()"));
  4237 	iDescriptors.UpdateDescriptorsHs();
  4238 	}
  4239 
  4240 
  4241 //
  4242 // Called whenever either iOtgClientConnect or iClientSupportReady changes value.
  4243 //
  4244 TInt DUsbClientController::EvaluateOtgConnectFlags()
  4245 	{
  4246 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EvaluateOtgConnectFlags()"));
  4247 
  4248 	TInt r = KErrNone;
  4249 
  4250 	// Check to see if the current flag states result in a change to the
  4251 	// need to activate the DPLUS pull-up
  4252 	TBool enableDPlus;
  4253 	if (!iOtgHnpHandledByHw)
  4254 		{
  4255 		// the default
  4256 		enableDPlus = (iOtgClientConnect && iClientSupportReady);
  4257 		}
  4258 	else
  4259 		{
  4260 		// certain h/w: handles HNP connect/disconnect automatically
  4261 		__KTRACE_OPT(KUSB, Kern::Printf("  HNP-handling h/w: only considering user-side readiness"));
  4262 		enableDPlus = iClientSupportReady;
  4263 		}
  4264 
  4265 	if (enableDPlus == iDPlusEnabled)
  4266 		{
  4267 		return r;
  4268 		}
  4269 
  4270 	// There has been a changed requirement that must be serviced...
  4271 	if (enableDPlus)
  4272 		{
  4273 		__KTRACE_OPT(KUSB, Kern::Printf("  calling (*iEnablePullUpOnDPlus)()"));
  4274 		if (iEnablePullUpOnDPlus != NULL)
  4275 			{
  4276 			iDPlusEnabled = enableDPlus;
  4277 			// First we move to Suspend state to trigger a state change
  4278 			// notification in any case, even if no cable and/or host are
  4279 			// connected. The next Reset will get us out of it again.
  4280 			iDeviceStateB4Suspend = iDeviceState;
  4281 			NextDeviceState(EUsbcDeviceStateSuspended);
  4282 			r = (*iEnablePullUpOnDPlus)(iOtgContext);
  4283 			if (r != KErrNone)
  4284 				{
  4285 				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: iEnablePullUpOnDPlus() = %d", r));
  4286 				}
  4287 			}
  4288 		else
  4289 			{
  4290 			__KTRACE_OPT(KUSB, Kern::Printf("  Warning: iEnablePullUpOnDPlus pointer not ready"));
  4291 			// We cannot enforce the presence of the pointer (via an ASSERT)
  4292 			// since it might only be available at a later point.
  4293 			// We shouldn't return an error at this point either, since the
  4294 			// problem will be a systematic one.
  4295 			}
  4296 		}
  4297 	else
  4298 		{
  4299 		__KTRACE_OPT(KUSB, Kern::Printf("  calling (*iDisablePullUpOnDPlus)()"));
  4300 		if (iDisablePullUpOnDPlus != NULL)
  4301 			{
  4302 			iDPlusEnabled = enableDPlus;
  4303 			r = (*iDisablePullUpOnDPlus)(iOtgContext);
  4304 			if (r != KErrNone)
  4305 				{
  4306 				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: iDisablePullUpOnDPlus() = %d", r));
  4307 				}
  4308 			}
  4309 		else
  4310 			{
  4311 			__KTRACE_OPT(KUSB, Kern::Printf("  Warning: iDisablePullUpOnDPlus pointer not ready"));
  4312 			// We cannot enforce the presence of the pointer (via an ASSERT)
  4313 			// since it might only be available at a later point.
  4314 			// We shouldn't return an error at this point either, since the
  4315 			// problem will be a systematic one.
  4316 			}
  4317 		}
  4318 	return r;
  4319 	}
  4320 
  4321 
  4322 //
  4323 // DFC (static)
  4324 //
  4325 void DUsbClientController::ReconnectTimerCallback(TAny *aPtr)
  4326 	{
  4327 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ReconnectTimerCallback()"));
  4328 	if (!aPtr)
  4329 		{
  4330 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: !aPtr"));
  4331 		return;
  4332 		}
  4333 	DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
  4334 	ptr->UsbConnect();
  4335 	}
  4336 
  4337 
  4338 //
  4339 // ISR (static)
  4340 //
  4341 void DUsbClientController::CableStatusTimerCallback(TAny *aPtr)
  4342 	{
  4343 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::CableStatusTimerCallback()"));
  4344 	if (!aPtr)
  4345 		{
  4346 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: !aPtr"));
  4347 		return;
  4348 		}
  4349 	DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
  4350 	ptr->ProcessSuspendEventProceed();
  4351 	}
  4352 
  4353 
  4354 //
  4355 // static
  4356 //
  4357 void DUsbClientController::PowerUpDfc(TAny* aPtr)
  4358 	{
  4359 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerUpDfc"));
  4360 	if (!aPtr)
  4361 		{
  4362 		__KTRACE_OPT(KPANIC, Kern::Printf("	 Error: !aPtr"));
  4363 		return;
  4364 		}
  4365 	DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
  4366 	__PM_ASSERT(ptr->iStandby);
  4367 	(void) ptr->PowerUp();
  4368 	ptr->iStandby = EFalse;
  4369 	ptr->iPowerHandler->PowerUpDone();
  4370 	}
  4371 
  4372 
  4373 //
  4374 // static
  4375 //
  4376 void DUsbClientController::PowerDownDfc(TAny* aPtr)
  4377 	{
  4378 	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::PowerDownDfc"));
  4379 	if (!aPtr)
  4380 		{
  4381 		__KTRACE_OPT(KPANIC, Kern::Printf("	 Error: !aPtr"));
  4382 		return;
  4383 		}
  4384 	DUsbClientController* const ptr = static_cast<DUsbClientController*>(aPtr);
  4385 	__PM_ASSERT(!ptr->iStandby);
  4386 	ptr->iStandby = ETrue;
  4387 	// We might not want to power down when the UDC is active:
  4388 	if (!ptr->iHardwareActivated || ptr->PowerDownWhenActive())
  4389 		{
  4390 		(void) ptr->PowerDown();
  4391 		__KTRACE_OPT(KUSB, Kern::Printf("Calling PowerHandler->PowerDownDone()"));
  4392 		ptr->iPowerHandler->PowerDownDone();
  4393 		}
  4394 	else
  4395 		{
  4396 		__KTRACE_OPT(KUSB, Kern::Printf("Not calling PowerHandler->PowerDownDone()"));
  4397 		__KTRACE_OPT(KUSB, Kern::Printf("  because UDC is active."));
  4398 		}
  4399 	}
  4400 
  4401 
  4402 // -EOF-