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