os/kernelhwsrv/kernel/eka/drivers/usbcc/chapter9.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/chapter9.cpp
sl@0
    15
// Platform independent layer (PIL) of the USB Device controller driver:
sl@0
    16
// Processing of USB spec chapter 9 standard requests.
sl@0
    17
// 
sl@0
    18
//
sl@0
    19
sl@0
    20
/**
sl@0
    21
 @file chapter9.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
//#define ENABLE_EXCESSIVE_DEBUG_OUTPUT
sl@0
    29
sl@0
    30
//
sl@0
    31
// The way functions are called after an request has been completed by the PSL:
sl@0
    32
//
sl@0
    33
//                                         Ep0RequestComplete
sl@0
    34
//                                                 |
sl@0
    35
//                                        ------------------------------------------------
sl@0
    36
//                                       |                                                |
sl@0
    37
//                              ProcessEp0ReceiveDone                            ProcessEp0TransmitDone
sl@0
    38
//                                       |                                                |
sl@0
    39
//                   ---------------------------------------                              |
sl@0
    40
//                  |                                       |                             |
sl@0
    41
//        ProcessEp0SetupReceived                 ProcessEp0DataReceived        ProcessDataTransferDone
sl@0
    42
//                  |                                       |
sl@0
    43
//         ---------------------                      ---------------
sl@0
    44
//        |                     |                    |               |
sl@0
    45
//   ProcessXXX       ProcessDataTransferDone   ProceedXXX  ProcessDataTransferDone
sl@0
    46
//
sl@0
    47
//   XXX = Specific_Request
sl@0
    48
//
sl@0
    49
sl@0
    50
//
sl@0
    51
// === USB Controller member function implementation - PSL API (protected) ========================
sl@0
    52
//
sl@0
    53
sl@0
    54
/** Used to synchronize the Ep0 state machine between the PSL and PIL.
sl@0
    55
	Accepts a SETUP packet and returns the next Ep0 state.
sl@0
    56
sl@0
    57
	@param aSetupBuf The SETUP packet just received by the PSL.
sl@0
    58
	@return The next Ep0 state.
sl@0
    59
sl@0
    60
	@publishedPartner @released
sl@0
    61
*/
sl@0
    62
TUsbcEp0State DUsbClientController::EnquireEp0NextState(const TUint8* aSetupBuf) const
sl@0
    63
	{
sl@0
    64
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnquireEp0NextState()"));
sl@0
    65
sl@0
    66
	// This function may be called by the PSL from within an ISR -- so we have
sl@0
    67
	// to take care what we do here (and also in all functions that get called
sl@0
    68
	// from here).
sl@0
    69
sl@0
    70
	if (SWAP_BYTES_16((reinterpret_cast<const TUint16*>(aSetupBuf)[3])) == 0) // iLength
sl@0
    71
		{
sl@0
    72
		__KTRACE_OPT(KUSB, Kern::Printf("  --> EEp0StateStatusIn"));
sl@0
    73
		return EEp0StateStatusIn;							// No-data Control => Status_IN
sl@0
    74
		}
sl@0
    75
	else if ((aSetupBuf[0] & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev)
sl@0
    76
		{
sl@0
    77
		__KTRACE_OPT(KUSB, Kern::Printf("  --> EEp0StateDataOut"));
sl@0
    78
		return EEp0StateDataOut;							// Control Write => Data_OUT
sl@0
    79
		}
sl@0
    80
	else
sl@0
    81
		{
sl@0
    82
		__KTRACE_OPT(KUSB, Kern::Printf("  --> EEp0StateDataIn"));
sl@0
    83
		return EEp0StateDataIn;								// Control Read => Data_IN
sl@0
    84
		}
sl@0
    85
	}
sl@0
    86
sl@0
    87
sl@0
    88
TInt DUsbClientController::ProcessEp0ReceiveDone(TInt aCount)
sl@0
    89
	{
sl@0
    90
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0ReceiveDone()"));
sl@0
    91
	TInt r;
sl@0
    92
	if (iEp0DataReceiving == EFalse)
sl@0
    93
		{
sl@0
    94
		// It's obviously a Setup packet, so...
sl@0
    95
		r = ProcessEp0SetupReceived(aCount);
sl@0
    96
		}
sl@0
    97
	else
sl@0
    98
		{
sl@0
    99
		// If it isn't a Setup, it must be data...
sl@0
   100
		// (This is actually not quite true, as it could also be - in theory - a new Setup packet
sl@0
   101
		//  when the host has abandoned, for whatever reason, the previous one which was still
sl@0
   102
		//  in progress. However no such case is known to have occurred with this driver, or at
sl@0
   103
		//  least it didn't lead to problems.
sl@0
   104
		//  Some UDCs have a dedicated interrupt for Setup packets, but so far this driver hasn't
sl@0
   105
		//  made use of such a feature (as it would require a PSL/PIL API change).)
sl@0
   106
		r = ProcessEp0DataReceived(aCount);
sl@0
   107
		}
sl@0
   108
	return r;
sl@0
   109
	}
sl@0
   110
sl@0
   111
sl@0
   112
TInt DUsbClientController::ProcessEp0TransmitDone(TInt aCount, TInt aError)
sl@0
   113
	{
sl@0
   114
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0TransmitDone()"));
sl@0
   115
	// In any case: there's now no longer a write pending
sl@0
   116
	iEp0WritePending = EFalse;
sl@0
   117
	// If it was a client who set up this transmission, we report to that client
sl@0
   118
	if (iEp0ClientDataTransmitting)
sl@0
   119
		{
sl@0
   120
		iEp0ClientDataTransmitting = EFalse;
sl@0
   121
		TUsbcRequestCallback* const p = iRequestCallbacks[KEp0_Tx];
sl@0
   122
		if (p)
sl@0
   123
			{
sl@0
   124
			__ASSERT_DEBUG((p->iTransferDir == EControllerWrite), Kern::Fault(KUsbPILPanicCat, __LINE__));
sl@0
   125
			p->iError = aError;
sl@0
   126
			p->iTxBytes = aCount;
sl@0
   127
			ProcessDataTransferDone(*p);
sl@0
   128
			return KErrNone;
sl@0
   129
			}
sl@0
   130
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: DUsbClientController::ProcessEpTransmitDone: Stalling Ep0"));
sl@0
   131
		StallEndpoint(KEp0_In);								// request not found
sl@0
   132
		return KErrNotFound;
sl@0
   133
		}
sl@0
   134
	// If _we_ sent the data, we simply do nothing here...
sl@0
   135
	return KErrNone;
sl@0
   136
	}
sl@0
   137
sl@0
   138
sl@0
   139
#define USB_PROCESS_REQUEST(request) \
sl@0
   140
	if (Process ## request(packet) != KErrNone) \
sl@0
   141
		{ \
sl@0
   142
		__KTRACE_OPT(KUSB, \
sl@0
   143
					 Kern::Printf("  ProcessEp0SetupReceived: Stalling Ep0")); \
sl@0
   144
		StallEndpoint(KEp0_In); \
sl@0
   145
		}
sl@0
   146
sl@0
   147
TInt DUsbClientController::ProcessEp0SetupReceived(TInt aCount)
sl@0
   148
	{
sl@0
   149
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0SetupReceived()"));
sl@0
   150
sl@0
   151
	if (aCount > iEp0MaxPacketSize)
sl@0
   152
		{
sl@0
   153
		// Fatal error: too much data!
sl@0
   154
		aCount = iEp0MaxPacketSize;
sl@0
   155
		}
sl@0
   156
sl@0
   157
	// first we split the data into meaningful units:
sl@0
   158
	TUsbcSetup packet;
sl@0
   159
	Buffer2Setup(iEp0_RxBuf, packet);
sl@0
   160
sl@0
   161
#if defined(_DEBUG) && defined(ENABLE_EXCESSIVE_DEBUG_OUTPUT)
sl@0
   162
	// let's see what we've got:
sl@0
   163
	__KTRACE_OPT(KUSB, Kern::Printf("  bmRequestType = 0x%02x", packet.iRequestType));
sl@0
   164
	if ((packet.iRequestType & KUsbRequestType_TypeMask) == KUsbRequestType_TypeStd)
sl@0
   165
		{
sl@0
   166
		switch (packet.iRequest)
sl@0
   167
			{
sl@0
   168
		case KUsbRequest_GetStatus:
sl@0
   169
			__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (GET_STATUS)",
sl@0
   170
											KUsbRequest_GetStatus));
sl@0
   171
			break;
sl@0
   172
		case KUsbRequest_ClearFeature:
sl@0
   173
			__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (CLEAR_FEATURE)",
sl@0
   174
											KUsbRequest_ClearFeature));
sl@0
   175
			break;
sl@0
   176
		case KUsbRequest_SetFeature:
sl@0
   177
			__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (SET_FEATURE)",
sl@0
   178
											KUsbRequest_SetFeature));
sl@0
   179
			break;
sl@0
   180
		case KUsbRequest_SetAddress:
sl@0
   181
			__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (SET_ADDRESS)",
sl@0
   182
											KUsbRequest_SetAddress));
sl@0
   183
			break;
sl@0
   184
		case KUsbRequest_GetDescriptor:
sl@0
   185
			__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (GET_DESCRIPTOR)",
sl@0
   186
											KUsbRequest_GetDescriptor));
sl@0
   187
			break;
sl@0
   188
		case KUsbRequest_SetDescriptor:
sl@0
   189
			__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (SET_DESCRIPTOR)",
sl@0
   190
											KUsbRequest_SetDescriptor));
sl@0
   191
			break;
sl@0
   192
		case KUsbRequest_GetConfig:
sl@0
   193
			__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (GET_CONFIGURATION)",
sl@0
   194
											KUsbRequest_GetConfig));
sl@0
   195
			break;
sl@0
   196
		case KUsbRequest_SetConfig:
sl@0
   197
			__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (SET_CONFIGURATION)",
sl@0
   198
											KUsbRequest_SetConfig));
sl@0
   199
			break;
sl@0
   200
		case KUsbRequest_GetInterface:
sl@0
   201
			__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (GET_INTERFACE)",
sl@0
   202
											KUsbRequest_GetInterface));
sl@0
   203
			break;
sl@0
   204
		case KUsbRequest_SetInterface:
sl@0
   205
			__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (SET_INTERFACE)",
sl@0
   206
											KUsbRequest_SetInterface));
sl@0
   207
			break;
sl@0
   208
		case KUsbRequest_SynchFrame:
sl@0
   209
			__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (SYNCH_FRAME)",
sl@0
   210
											KUsbRequest_SynchFrame));
sl@0
   211
			break;
sl@0
   212
		default:
sl@0
   213
			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: bRequest = 0x%02x (UNKNWON STANDARD REQUEST)",
sl@0
   214
											  packet.iRequest));
sl@0
   215
			break;
sl@0
   216
			}
sl@0
   217
		}
sl@0
   218
	else
sl@0
   219
		{
sl@0
   220
		__KTRACE_OPT(KUSB, Kern::Printf("  bRequest      = 0x%02x (NON-STANDARD REQUEST)",
sl@0
   221
										packet.iRequest));
sl@0
   222
		}
sl@0
   223
	__KTRACE_OPT(KUSB, Kern::Printf("  wValue        = 0x%04x", packet.iValue));
sl@0
   224
	__KTRACE_OPT(KUSB, Kern::Printf("  wIndex        = 0x%04x", packet.iIndex));
sl@0
   225
	__KTRACE_OPT(KUSB, Kern::Printf("  wLength       = 0x%04x", packet.iLength));
sl@0
   226
#endif // defined(_DEBUG) && defined(ENABLE_EXCESSIVE_DEBUG_OUTPUT)
sl@0
   227
sl@0
   228
	// now the actual analysis
sl@0
   229
	if ((packet.iRequestType & KUsbRequestType_TypeMask) == KUsbRequestType_TypeStd)
sl@0
   230
		{
sl@0
   231
		iEp0ReceivedNonStdRequest = EFalse;
sl@0
   232
		switch (packet.iRequest)
sl@0
   233
			{
sl@0
   234
		case KUsbRequest_GetStatus:
sl@0
   235
			switch (packet.iRequestType & KUsbRequestType_DestMask)
sl@0
   236
				{ // Recipient
sl@0
   237
			case KUsbRequestType_DestDevice:
sl@0
   238
				USB_PROCESS_REQUEST(GetDeviceStatus);
sl@0
   239
				break;
sl@0
   240
			case KUsbRequestType_DestIfc:
sl@0
   241
				USB_PROCESS_REQUEST(GetInterfaceStatus);
sl@0
   242
				break;
sl@0
   243
			case KUsbRequestType_DestEp:
sl@0
   244
				USB_PROCESS_REQUEST(GetEndpointStatus);
sl@0
   245
				break;
sl@0
   246
			default:
sl@0
   247
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: GET STATUS - Other or Unknown recipient"));
sl@0
   248
				__KTRACE_OPT(KPANIC, Kern::Printf("  -> DUsbClientController::ProcessEp0SetupReceived: "
sl@0
   249
												  "Stalling Ep0"));
sl@0
   250
				StallEndpoint(KEp0_In);
sl@0
   251
				break;
sl@0
   252
				}
sl@0
   253
			break;
sl@0
   254
		case KUsbRequest_ClearFeature:
sl@0
   255
		case KUsbRequest_SetFeature:
sl@0
   256
			switch (packet.iRequestType & KUsbRequestType_DestMask)
sl@0
   257
				{ // Recipient
sl@0
   258
			case KUsbRequestType_DestDevice:
sl@0
   259
				USB_PROCESS_REQUEST(SetClearDevFeature);
sl@0
   260
				break;
sl@0
   261
			case KUsbRequestType_DestIfc:
sl@0
   262
				USB_PROCESS_REQUEST(SetClearIfcFeature);
sl@0
   263
				break;
sl@0
   264
			case KUsbRequestType_DestEp:
sl@0
   265
				USB_PROCESS_REQUEST(SetClearEpFeature);
sl@0
   266
				break;
sl@0
   267
			default:
sl@0
   268
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: SET/CLEAR FEATURE - "
sl@0
   269
												  "Other or Unknown recipient"));
sl@0
   270
				__KTRACE_OPT(KPANIC, Kern::Printf("  -> Stalling Ep0"));
sl@0
   271
				StallEndpoint(KEp0_In);
sl@0
   272
				break;
sl@0
   273
				}
sl@0
   274
			break;
sl@0
   275
		case KUsbRequest_SetAddress:
sl@0
   276
			USB_PROCESS_REQUEST(SetAddress);
sl@0
   277
			break;
sl@0
   278
		case KUsbRequest_GetDescriptor:
sl@0
   279
			USB_PROCESS_REQUEST(GetDescriptor);
sl@0
   280
			break;
sl@0
   281
		case KUsbRequest_SetDescriptor:
sl@0
   282
			USB_PROCESS_REQUEST(SetDescriptor);
sl@0
   283
			break;
sl@0
   284
		case KUsbRequest_GetConfig:
sl@0
   285
			USB_PROCESS_REQUEST(GetConfiguration);
sl@0
   286
			break;
sl@0
   287
		case KUsbRequest_SetConfig:
sl@0
   288
			USB_PROCESS_REQUEST(SetConfiguration);
sl@0
   289
			break;
sl@0
   290
		case KUsbRequest_GetInterface:
sl@0
   291
			USB_PROCESS_REQUEST(GetInterface);
sl@0
   292
			break;
sl@0
   293
		case KUsbRequest_SetInterface:
sl@0
   294
			USB_PROCESS_REQUEST(SetInterface);
sl@0
   295
			break;
sl@0
   296
		case KUsbRequest_SynchFrame:
sl@0
   297
			USB_PROCESS_REQUEST(SynchFrame);
sl@0
   298
			break;
sl@0
   299
		default:
sl@0
   300
			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown/unsupported Std Setup Request"));
sl@0
   301
			__KTRACE_OPT(KPANIC, Kern::Printf("  -> Stalling Ep0"));
sl@0
   302
			StallEndpoint(KEp0_In);
sl@0
   303
			break;
sl@0
   304
			}
sl@0
   305
		}
sl@0
   306
	else
sl@0
   307
		{
sl@0
   308
		// Type mask != KUsbRequestType_TypeStd => class- or vendor-specific request
sl@0
   309
		iEp0ReceivedNonStdRequest = ETrue;
sl@0
   310
		const DBase* client = NULL;
sl@0
   311
		switch (packet.iRequestType & KUsbRequestType_DestMask)
sl@0
   312
			{ // Recipient
sl@0
   313
		case KUsbRequestType_DestDevice:
sl@0
   314
			client = iEp0DeviceControl;
sl@0
   315
			break;
sl@0
   316
		case KUsbRequestType_DestIfc:
sl@0
   317
			if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
sl@0
   318
				{
sl@0
   319
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   320
				}
sl@0
   321
			else
sl@0
   322
				{
sl@0
   323
				const TUsbcInterfaceSet* const ifcset_ptr =
sl@0
   324
					InterfaceNumber2InterfacePointer(packet.iIndex);
sl@0
   325
				if (ifcset_ptr)
sl@0
   326
					{
sl@0
   327
					if (ifcset_ptr->CurrentInterface()->iNoEp0Requests)
sl@0
   328
						{
sl@0
   329
						__KTRACE_OPT(KUSB, Kern::Printf("  Recipient says: NoEp0RequestsPlease"));
sl@0
   330
						}
sl@0
   331
					else
sl@0
   332
						{
sl@0
   333
						client = ifcset_ptr->iClientId;
sl@0
   334
						}
sl@0
   335
					}
sl@0
   336
				else
sl@0
   337
					{
sl@0
   338
					__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface 0x%02x does not exist",
sl@0
   339
													  packet.iIndex));
sl@0
   340
					}
sl@0
   341
				}
sl@0
   342
			break;
sl@0
   343
		case KUsbRequestType_DestEp:
sl@0
   344
			if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
sl@0
   345
				{
sl@0
   346
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   347
				}
sl@0
   348
			else if (EndpointExists(packet.iIndex) == EFalse)
sl@0
   349
				{
sl@0
   350
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint 0x%02x does not exist",
sl@0
   351
												  packet.iIndex));
sl@0
   352
				}
sl@0
   353
			else
sl@0
   354
				{
sl@0
   355
				const TInt idx = EpAddr2Idx(packet.iIndex);
sl@0
   356
				const TUsbcInterfaceSet* const ifcset_ptr =
sl@0
   357
					iRealEndpoints[idx].iLEndpoint->iInterface->iInterfaceSet;
sl@0
   358
				if (ifcset_ptr->CurrentInterface()->iNoEp0Requests)
sl@0
   359
					{
sl@0
   360
					__KTRACE_OPT(KUSB, Kern::Printf("  Recipient says: NoEp0RequestsPlease"));
sl@0
   361
					}
sl@0
   362
				else
sl@0
   363
					{
sl@0
   364
					client = ifcset_ptr->iClientId;
sl@0
   365
					}
sl@0
   366
				}
sl@0
   367
			break;
sl@0
   368
		default:
sl@0
   369
			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Other or Unknown recipient"));
sl@0
   370
			break;
sl@0
   371
			}
sl@0
   372
		if (client != NULL)
sl@0
   373
			{
sl@0
   374
			// Try to relay packet to the appropriate recipient
sl@0
   375
			TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
sl@0
   376
			TUsbcRequestCallback* p;
sl@0
   377
			while ((p = iter++) != NULL)
sl@0
   378
				{
sl@0
   379
				if (p->Owner() == client)
sl@0
   380
					{
sl@0
   381
					__ASSERT_DEBUG((p->iEndpointNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
sl@0
   382
					__ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__));
sl@0
   383
					__KTRACE_OPT(KUSB, Kern::Printf("  Found Ep0 read request"));
sl@0
   384
					if (packet.iLength != 0)
sl@0
   385
						{
sl@0
   386
						if ((packet.iRequestType & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev)
sl@0
   387
							{
sl@0
   388
							// Data transfer & direction OUT => there'll be a DATA_OUT stage
sl@0
   389
							__KTRACE_OPT(KUSB, Kern::Printf("  Next is DATA_OUT: setting up DataOutVars"));
sl@0
   390
							SetEp0DataOutVars(packet, client);
sl@0
   391
							}
sl@0
   392
						else if ((packet.iRequestType & KUsbRequestType_DirMask) == KUsbRequestType_DirToHost)
sl@0
   393
							{
sl@0
   394
							// For possible later use (ZLP).
sl@0
   395
							iEp0_TxNonStdCount = packet.iLength;
sl@0
   396
							}
sl@0
   397
						}
sl@0
   398
					memcpy(p->iBufferStart, iEp0_RxBuf, aCount);
sl@0
   399
					p->iError = KErrNone;					// if it wasn't 'KErrNone' we wouldn't be here
sl@0
   400
					*(p->iPacketSize) = aCount;
sl@0
   401
					p->iRxPackets = 1;
sl@0
   402
					*(p->iPacketIndex) = 0;
sl@0
   403
					ProcessDataTransferDone(*p);
sl@0
   404
					return KErrNone;
sl@0
   405
					}
sl@0
   406
				}
sl@0
   407
			__KTRACE_OPT(KUSB, Kern::Printf("  Ep0 read request not found: setting RxExtra vars (Setup)"));
sl@0
   408
			iEp0_RxExtraCount = aCount;
sl@0
   409
			iEp0_RxExtraData = ETrue;
sl@0
   410
			return KErrNotFound;
sl@0
   411
			}
sl@0
   412
		else // if (client == NULL)
sl@0
   413
			{
sl@0
   414
			__KTRACE_OPT(KPANIC, Kern::Printf("  Ep0 request error: Stalling Ep0"));
sl@0
   415
			StallEndpoint(KEp0_In);
sl@0
   416
			return KErrGeneral;
sl@0
   417
			}
sl@0
   418
		}
sl@0
   419
	return KErrNone;
sl@0
   420
	}
sl@0
   421
sl@0
   422
#undef USB_PROCESS_REQUEST
sl@0
   423
sl@0
   424
sl@0
   425
TInt DUsbClientController::ProcessEp0DataReceived(TInt aCount)
sl@0
   426
	{
sl@0
   427
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0DataReceived()"));
sl@0
   428
sl@0
   429
	__KTRACE_OPT(KUSB, Kern::Printf("  : %d bytes", aCount));
sl@0
   430
sl@0
   431
	if (aCount > iEp0MaxPacketSize)
sl@0
   432
		{
sl@0
   433
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Too much data"));
sl@0
   434
		aCount = iEp0MaxPacketSize;
sl@0
   435
		}
sl@0
   436
	iEp0DataReceived += aCount;
sl@0
   437
	if (iEp0ClientId == NULL)
sl@0
   438
		{
sl@0
   439
		// it is us (not an app), who owns this transaction
sl@0
   440
		switch (iSetup.iRequest)
sl@0
   441
			{
sl@0
   442
#ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
sl@0
   443
		case KUsbRequest_SetDescriptor:
sl@0
   444
			memcpy(iEp0_RxCollectionBuf + iEp0DataReceived, iEp0_RxBuf, aCount);
sl@0
   445
			ProceedSetDescriptor();
sl@0
   446
			break;
sl@0
   447
#endif
sl@0
   448
		default:
sl@0
   449
			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: invalid request in iSetup"));
sl@0
   450
			__KTRACE_OPT(KPANIC, Kern::Printf("  -> DUsbClientController::ProcessEp0DataReceived: Stalling Ep0"));
sl@0
   451
			StallEndpoint(KEp0_In);
sl@0
   452
			ResetEp0DataOutVars();
sl@0
   453
			break;
sl@0
   454
			}
sl@0
   455
		}
sl@0
   456
	else
sl@0
   457
		{
sl@0
   458
		// pass the data on to a client
sl@0
   459
		TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks);
sl@0
   460
		TUsbcRequestCallback* p;
sl@0
   461
		while ((p = iter++) != NULL)
sl@0
   462
			{
sl@0
   463
			if (p->Owner() == iEp0ClientId)
sl@0
   464
				{
sl@0
   465
				__ASSERT_DEBUG((p->iEndpointNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__));
sl@0
   466
				__ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__));
sl@0
   467
				__KTRACE_OPT(KUSB, Kern::Printf("  Found Ep0 read request"));
sl@0
   468
				memcpy(p->iBufferStart, iEp0_RxBuf, aCount);
sl@0
   469
				p->iError = KErrNone;						// if it wasn't 'KErrNone' we wouldn't be here
sl@0
   470
				*(p->iPacketSize) = aCount;
sl@0
   471
				p->iRxPackets = 1;
sl@0
   472
				*(p->iPacketIndex) = 0;
sl@0
   473
				ProcessDataTransferDone(*p);
sl@0
   474
				goto found;
sl@0
   475
				}
sl@0
   476
			}
sl@0
   477
		__KTRACE_OPT(KUSB, Kern::Printf("  Ep0 read request not found: setting RxExtra vars (Data)"));
sl@0
   478
		iEp0_RxExtraCount = aCount;
sl@0
   479
		iEp0_RxExtraData = ETrue;
sl@0
   480
		iEp0DataReceived -= aCount;
sl@0
   481
		return KErrNotFound;
sl@0
   482
		}
sl@0
   483
 found:
sl@0
   484
	if (iEp0DataReceived >= iSetup.iLength)
sl@0
   485
		{
sl@0
   486
		// all data seems now to be here
sl@0
   487
		ResetEp0DataOutVars();
sl@0
   488
		}
sl@0
   489
	return KErrNone;
sl@0
   490
	}
sl@0
   491
sl@0
   492
sl@0
   493
// --- The USB Spec Chapter 9 Standard Endpoint Zero Device Requests ---
sl@0
   494
sl@0
   495
TInt DUsbClientController::ProcessGetDeviceStatus(const TUsbcSetup& aPacket)
sl@0
   496
	{
sl@0
   497
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetDeviceStatus()"));
sl@0
   498
	if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
sl@0
   499
		{
sl@0
   500
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   501
		return KErrGeneral;
sl@0
   502
		}
sl@0
   503
	const TUint16 status = ((DeviceSelfPowered() ? KUsbDevStat_SelfPowered : 0) |
sl@0
   504
					  (iRmWakeupStatus_Enabled ? KUsbDevStat_RemoteWakeup : 0));
sl@0
   505
	__KTRACE_OPT(KUSB, Kern::Printf("  Reporting device status: 0x%02x", status));
sl@0
   506
	*reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status);
sl@0
   507
	if (SetupEndpointZeroWrite(iEp0_TxBuf, sizeof(status)) == KErrNone)
sl@0
   508
		{
sl@0
   509
		iEp0WritePending = ETrue;
sl@0
   510
		}
sl@0
   511
	return KErrNone;
sl@0
   512
	}
sl@0
   513
sl@0
   514
sl@0
   515
TInt DUsbClientController::ProcessGetInterfaceStatus(const TUsbcSetup& aPacket)
sl@0
   516
	{
sl@0
   517
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetInterfaceStatus()"));
sl@0
   518
	if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
sl@0
   519
		{
sl@0
   520
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   521
		return KErrGeneral;
sl@0
   522
		}
sl@0
   523
	if (InterfaceExists(aPacket.iIndex) == EFalse)
sl@0
   524
		{
sl@0
   525
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Interface does not exist"));
sl@0
   526
		return KErrGeneral;
sl@0
   527
		}
sl@0
   528
	const TUint16 status = 0x0000;							// as of USB Spec 2.0
sl@0
   529
	__KTRACE_OPT(KUSB, Kern::Printf("  Reporting interface status: 0x%02x", status));
sl@0
   530
	*reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status);
sl@0
   531
	if (SetupEndpointZeroWrite(iEp0_TxBuf, sizeof(status)) == KErrNone)
sl@0
   532
		{
sl@0
   533
		iEp0WritePending = ETrue;
sl@0
   534
		}
sl@0
   535
	return KErrNone;
sl@0
   536
	}
sl@0
   537
sl@0
   538
sl@0
   539
TInt DUsbClientController::ProcessGetEndpointStatus(const TUsbcSetup& aPacket)
sl@0
   540
	{
sl@0
   541
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetEndpointStatus()"));
sl@0
   542
	if (iTrackDeviceState &&
sl@0
   543
		((iDeviceState < EUsbcDeviceStateAddress) ||
sl@0
   544
		 (iDeviceState == EUsbcDeviceStateAddress && (aPacket.iIndex & KUsbEpAddress_Portmask) != 0)))
sl@0
   545
		{
sl@0
   546
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   547
		return KErrGeneral;
sl@0
   548
		}
sl@0
   549
	if (EndpointExists(aPacket.iIndex) == EFalse)
sl@0
   550
		{
sl@0
   551
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint does not exist"));
sl@0
   552
		return KErrGeneral;
sl@0
   553
		}
sl@0
   554
	const TInt ep = EpAddr2Idx(aPacket.iIndex);
sl@0
   555
	const TUint16 status = (iRealEndpoints[ep].iHalt) ?	 KUsbEpStat_Halt : 0;
sl@0
   556
	__KTRACE_OPT(KUSB, Kern::Printf("  Reporting endpoint status 0x%02x for real endpoint %d",
sl@0
   557
									status, ep));
sl@0
   558
	*reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status);
sl@0
   559
	if (SetupEndpointZeroWrite(iEp0_TxBuf, 2) == KErrNone)
sl@0
   560
		{
sl@0
   561
		iEp0WritePending = ETrue;
sl@0
   562
		}
sl@0
   563
	return KErrNone;
sl@0
   564
	}
sl@0
   565
sl@0
   566
sl@0
   567
TInt DUsbClientController::ProcessSetClearDevFeature(const TUsbcSetup& aPacket)
sl@0
   568
	{
sl@0
   569
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearDevFeature()"));
sl@0
   570
	if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateDefault)
sl@0
   571
		{
sl@0
   572
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   573
		return KErrGeneral;
sl@0
   574
		}
sl@0
   575
sl@0
   576
	TUint test_sel = 0;
sl@0
   577
sl@0
   578
	if (aPacket.iRequest == KUsbRequest_SetFeature)
sl@0
   579
		{
sl@0
   580
		switch (aPacket.iValue)
sl@0
   581
			{
sl@0
   582
		case KUsbFeature_RemoteWakeup:
sl@0
   583
			if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
sl@0
   584
				{
sl@0
   585
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   586
				return KErrGeneral;
sl@0
   587
				}
sl@0
   588
			iRmWakeupStatus_Enabled = ETrue;
sl@0
   589
			break;
sl@0
   590
		case KUsbFeature_TestMode:
sl@0
   591
			if (!iHighSpeed)
sl@0
   592
				{
sl@0
   593
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only supported in High-Speed mode"));
sl@0
   594
				return KErrGeneral;
sl@0
   595
				}
sl@0
   596
			if (LowByte(aPacket.iIndex) != 0)
sl@0
   597
				{
sl@0
   598
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Lower byte of wIndex must be zero"));
sl@0
   599
				return KErrGeneral;
sl@0
   600
				}
sl@0
   601
			test_sel = HighByte(aPacket.iIndex);
sl@0
   602
			if ((test_sel < KUsbTestSelector_Test_J) || (test_sel > KUsbTestSelector_Test_Force_Enable))
sl@0
   603
				{
sl@0
   604
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid test selector: %d", test_sel));
sl@0
   605
				return KErrGeneral;
sl@0
   606
				}
sl@0
   607
			break;
sl@0
   608
		case KUsbFeature_B_HnpEnable:
sl@0
   609
			if (!iOtgSupport)
sl@0
   610
				{
sl@0
   611
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only supported on a OTG device"));
sl@0
   612
				return KErrGeneral;
sl@0
   613
				}
sl@0
   614
			if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
sl@0
   615
				{
sl@0
   616
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only valid if OTG device supports HNP"));
sl@0
   617
				return KErrGeneral;
sl@0
   618
				}
sl@0
   619
			iOtgFuncMap |= KUsbOtgAttr_B_HnpEnable;
sl@0
   620
			OtgFeaturesNotify();
sl@0
   621
			break;
sl@0
   622
		case KUsbFeature_A_HnpSupport:
sl@0
   623
			if (!iOtgSupport)
sl@0
   624
				{
sl@0
   625
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only supported on a OTG device"));
sl@0
   626
				return KErrGeneral;
sl@0
   627
				}
sl@0
   628
			if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
sl@0
   629
				{
sl@0
   630
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only valid if OTG device supports HNP"));
sl@0
   631
				return KErrGeneral;
sl@0
   632
				}
sl@0
   633
			iOtgFuncMap |= KUsbOtgAttr_A_HnpSupport;
sl@0
   634
			OtgFeaturesNotify();
sl@0
   635
			break;
sl@0
   636
		case KUsbFeature_A_AltHnpSupport:
sl@0
   637
			if (!iOtgSupport)
sl@0
   638
				{
sl@0
   639
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only supported on a OTG device"));
sl@0
   640
				return KErrGeneral;
sl@0
   641
				}
sl@0
   642
			if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp))
sl@0
   643
				{
sl@0
   644
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Request only valid if OTG device supports HNP"));
sl@0
   645
				return KErrGeneral;
sl@0
   646
				}
sl@0
   647
			iOtgFuncMap |= KUsbOtgAttr_A_AltHnpSupport;
sl@0
   648
			OtgFeaturesNotify();
sl@0
   649
			break;
sl@0
   650
		default:
sl@0
   651
			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown feature requested"));
sl@0
   652
			return KErrGeneral;
sl@0
   653
			}
sl@0
   654
		}
sl@0
   655
	else // KUsbRequest_ClearFeature
sl@0
   656
		{
sl@0
   657
		switch (aPacket.iValue)
sl@0
   658
			{
sl@0
   659
		case KUsbFeature_RemoteWakeup:
sl@0
   660
			if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
sl@0
   661
				{
sl@0
   662
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   663
				return KErrGeneral;
sl@0
   664
				}
sl@0
   665
			iRmWakeupStatus_Enabled = EFalse;
sl@0
   666
			break;
sl@0
   667
		default:
sl@0
   668
			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown feature requested"));
sl@0
   669
			return KErrGeneral;
sl@0
   670
			}
sl@0
   671
		}
sl@0
   672
sl@0
   673
	SendEp0ZeroByteStatusPacket();							// success: zero bytes data during status stage
sl@0
   674
sl@0
   675
	// 9.4.9: "The transition to test mode of an upstream facing port must not happen until
sl@0
   676
	// after the status stage of the request."
sl@0
   677
	if (test_sel)
sl@0
   678
		{
sl@0
   679
		__KTRACE_OPT(KPANIC, Kern::Printf("  Entering HS Test Mode %d", test_sel));
sl@0
   680
		EnterTestMode(test_sel);
sl@0
   681
		}
sl@0
   682
sl@0
   683
	return KErrNone;
sl@0
   684
	}
sl@0
   685
sl@0
   686
sl@0
   687
TInt DUsbClientController::ProcessSetClearIfcFeature(const TUsbcSetup& aPacket)
sl@0
   688
	{
sl@0
   689
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearIfcFeature()"));
sl@0
   690
	if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
sl@0
   691
		{
sl@0
   692
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   693
		return KErrGeneral;
sl@0
   694
		}
sl@0
   695
	// No interface features defined in USB spec, thus
sl@0
   696
	return KErrGeneral;
sl@0
   697
	}
sl@0
   698
sl@0
   699
sl@0
   700
TInt DUsbClientController::ProcessSetClearEpFeature(const TUsbcSetup& aPacket)
sl@0
   701
	{
sl@0
   702
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearEpFeature()"));
sl@0
   703
	if (iTrackDeviceState &&
sl@0
   704
		((iDeviceState < EUsbcDeviceStateAddress) ||
sl@0
   705
		 (iDeviceState == EUsbcDeviceStateAddress && (aPacket.iIndex & KUsbEpAddress_Portmask) != 0)))
sl@0
   706
		{
sl@0
   707
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   708
		return KErrGeneral;
sl@0
   709
		}
sl@0
   710
	if (aPacket.iValue != KUsbFeature_EndpointHalt)
sl@0
   711
		{
sl@0
   712
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown feature requested"));
sl@0
   713
		return KErrGeneral;
sl@0
   714
		}
sl@0
   715
	if (EndpointExists(aPacket.iIndex) == EFalse)
sl@0
   716
		{
sl@0
   717
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint does not exist"));
sl@0
   718
		return KErrGeneral;
sl@0
   719
		}
sl@0
   720
	const TInt ep = EpAddr2Idx(aPacket.iIndex);
sl@0
   721
	if (iRealEndpoints[ep].iLEndpoint->iInfo.iType == KUsbEpTypeControl ||
sl@0
   722
		iRealEndpoints[ep].iLEndpoint->iInfo.iType == KUsbEpTypeIsochronous)
sl@0
   723
		{
sl@0
   724
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint is Control or Isochronous"));
sl@0
   725
		return KErrGeneral;
sl@0
   726
		}
sl@0
   727
	SetClearHaltFeature(ep, aPacket.iRequest);
sl@0
   728
	SendEp0ZeroByteStatusPacket();							// success: zero bytes data during status stage
sl@0
   729
	return KErrNone;
sl@0
   730
	}
sl@0
   731
sl@0
   732
sl@0
   733
TInt DUsbClientController::ProcessSetAddress(const TUsbcSetup& aPacket)
sl@0
   734
	{
sl@0
   735
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetAddress()"));
sl@0
   736
	if (iTrackDeviceState && iDeviceState > EUsbcDeviceStateAddress)
sl@0
   737
		{
sl@0
   738
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   739
		return KErrGeneral;
sl@0
   740
		}
sl@0
   741
	const TUint16 addr = aPacket.iValue;
sl@0
   742
	if (addr > 127)
sl@0
   743
		{
sl@0
   744
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Bad address value: %d (>127)", addr));
sl@0
   745
		return KErrGeneral;
sl@0
   746
		}
sl@0
   747
	if (addr == 0)
sl@0
   748
		{
sl@0
   749
		// Enter Default state (from Default or Address)
sl@0
   750
		NextDeviceState(EUsbcDeviceStateDefault);
sl@0
   751
		}
sl@0
   752
	__KTRACE_OPT(KUSB, Kern::Printf("  USB address: %d", addr));
sl@0
   753
	// The spec says, under section 9.4.6:
sl@0
   754
	// "Stages after the initial Setup packet assume the same device address as the Setup packet. The USB
sl@0
   755
	// device does not change its device address until after the Status stage of this request is completed
sl@0
   756
	// successfully. Note that this is a difference between this request and all other requests. For all other
sl@0
   757
	// requests, the operation indicated must be completed before the Status stage."
sl@0
   758
	// Therefore, here we first send the status packet and only then actually execute the request.
sl@0
   759
	SendEp0ZeroByteStatusPacket();
sl@0
   760
	SetDeviceAddress(addr);
sl@0
   761
	return KErrNone;
sl@0
   762
	}
sl@0
   763
sl@0
   764
sl@0
   765
TInt DUsbClientController::ProcessGetDescriptor(const TUsbcSetup& aPacket)
sl@0
   766
	{
sl@0
   767
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetDescriptor()"));
sl@0
   768
	if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateDefault)
sl@0
   769
		{
sl@0
   770
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   771
		return KErrGeneral;
sl@0
   772
		}
sl@0
   773
sl@0
   774
	// Make sure we assume the correct speed
sl@0
   775
	__ASSERT_DEBUG((iHighSpeed == CurrentlyUsingHighSpeed()), Kern::Fault(KUsbPILPanicCat, __LINE__));
sl@0
   776
sl@0
   777
	TInt size = 0;
sl@0
   778
	const TInt result = iDescriptors.FindDescriptor(HighByte(aPacket.iValue), // Type
sl@0
   779
													LowByte(aPacket.iValue), // Index
sl@0
   780
													aPacket.iIndex, // Language ID
sl@0
   781
													size);
sl@0
   782
sl@0
   783
	if ((result != KErrNone) || (size == 0))
sl@0
   784
		{
sl@0
   785
		// This doesn't have to be an error - protocol-wise it's OK.
sl@0
   786
		__KTRACE_OPT(KUSB, Kern::Printf("  Couldn't retrieve descriptor"));
sl@0
   787
		return KErrGeneral;
sl@0
   788
		}
sl@0
   789
sl@0
   790
	__KTRACE_OPT(KUSB, Kern::Printf("  Descriptor found, size: %d (requested: %d)",
sl@0
   791
									size, aPacket.iLength));
sl@0
   792
	if (size > KUsbcBufSz_Ep0Tx)
sl@0
   793
		{
sl@0
   794
		// This should actually not be possible (i.e. we should never get here).
sl@0
   795
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ep0_Tx buffer too small"));
sl@0
   796
		}
sl@0
   797
	if (size > aPacket.iLength)
sl@0
   798
		{
sl@0
   799
		// Send only as much data as requested by the host
sl@0
   800
		size = aPacket.iLength;
sl@0
   801
		}
sl@0
   802
sl@0
   803
#ifdef ENABLE_EXCESSIVE_DEBUG_OUTPUT
sl@0
   804
	__KTRACE_OPT(KUSB,
sl@0
   805
				 Kern::Printf("  Data: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ...",
sl@0
   806
							  iEp0_TxBuf[0], iEp0_TxBuf[1], iEp0_TxBuf[2], iEp0_TxBuf[3],
sl@0
   807
							  iEp0_TxBuf[4], iEp0_TxBuf[5], iEp0_TxBuf[6], iEp0_TxBuf[7]));
sl@0
   808
#endif
sl@0
   809
	// If we're about to send less bytes than expected by the host AND our number is a
sl@0
   810
	// multiple of the packet size, in order to indicate the end of the control transfer,
sl@0
   811
	// we must finally send a zero length data packet (ZLP):
sl@0
   812
	const TBool zlp = ((size < aPacket.iLength) && (size % iEp0MaxPacketSize == 0));
sl@0
   813
	if (SetupEndpointZeroWrite(iEp0_TxBuf, size, zlp) == KErrNone)
sl@0
   814
		{
sl@0
   815
		iEp0WritePending = ETrue;
sl@0
   816
		}
sl@0
   817
sl@0
   818
	return KErrNone;
sl@0
   819
	}
sl@0
   820
sl@0
   821
sl@0
   822
TInt DUsbClientController::ProcessSetDescriptor(const TUsbcSetup& aPacket)
sl@0
   823
	{
sl@0
   824
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetDescriptor()"));
sl@0
   825
#ifndef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
sl@0
   826
	return KErrGeneral;
sl@0
   827
#else
sl@0
   828
	if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
sl@0
   829
		{
sl@0
   830
		// Error: Invalid device state!
sl@0
   831
		return KErrGeneral;
sl@0
   832
		}
sl@0
   833
	if (aPacket.iLength > KUsbcBufSz_Ep0Rx)
sl@0
   834
		{
sl@0
   835
		// Error: Our Rx buffer is too small! (Raise a defect to make it larger)
sl@0
   836
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ep0_Rx buffer too small"));
sl@0
   837
		return KErrGeneral;
sl@0
   838
		}
sl@0
   839
	SetEp0DataOutVars(aPacket);
sl@0
   840
	SetupEndpointZeroRead();
sl@0
   841
	return KErrNone;
sl@0
   842
#endif
sl@0
   843
	}
sl@0
   844
sl@0
   845
sl@0
   846
TInt DUsbClientController::ProcessGetConfiguration(const TUsbcSetup& aPacket)
sl@0
   847
	{
sl@0
   848
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetConfiguration()"));
sl@0
   849
	if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
sl@0
   850
		{
sl@0
   851
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   852
		return KErrGeneral;
sl@0
   853
		}
sl@0
   854
	if (iTrackDeviceState && iDeviceState == EUsbcDeviceStateAddress && iCurrentConfig != 0)
sl@0
   855
		{
sl@0
   856
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: DeviceState Address && Config != 0"));
sl@0
   857
		return KErrGeneral;
sl@0
   858
		}
sl@0
   859
	if (iTrackDeviceState && iDeviceState == EUsbcDeviceStateConfigured && iCurrentConfig == 0)
sl@0
   860
		{
sl@0
   861
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: DeviceState Configured && Config == 0"));
sl@0
   862
		return KErrGeneral;
sl@0
   863
		}
sl@0
   864
	if (aPacket.iLength != 1)								// "unspecified behavior"
sl@0
   865
		{
sl@0
   866
		__KTRACE_OPT(KUSB, Kern::Printf("  Warning: wLength != 1 (= %d)", aPacket.iLength));
sl@0
   867
		}
sl@0
   868
	__KTRACE_OPT(KUSB, Kern::Printf("  Reporting configuration value %d", iCurrentConfig));
sl@0
   869
	if (SetupEndpointZeroWrite(&iCurrentConfig, sizeof(iCurrentConfig)) == KErrNone)
sl@0
   870
		{
sl@0
   871
		iEp0WritePending = ETrue;
sl@0
   872
		}
sl@0
   873
	return KErrNone;
sl@0
   874
	}
sl@0
   875
sl@0
   876
sl@0
   877
/** Changes the device's configuration value, including interface setup and/or
sl@0
   878
	teardown and state change notification of higher-layer clients.
sl@0
   879
	May also be called by the PSL in special cases - therefore publishedPartner.
sl@0
   880
sl@0
   881
	@param aPacket The received Ep0 SET_CONFIGURATION setup request packet.
sl@0
   882
	@return KErrGeneral in case of a protocol error, KErrNone otherwise.
sl@0
   883
sl@0
   884
	@publishedPartner @released
sl@0
   885
*/
sl@0
   886
TInt DUsbClientController::ProcessSetConfiguration(const TUsbcSetup& aPacket)
sl@0
   887
	{
sl@0
   888
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetConfiguration()"));
sl@0
   889
sl@0
   890
	// This function may be called by the PSL from within an ISR -- so we have
sl@0
   891
	// to take care what we do here (and also in all functions that get called
sl@0
   892
	// from here).
sl@0
   893
sl@0
   894
	if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress)
sl@0
   895
		{
sl@0
   896
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   897
		return KErrGeneral;
sl@0
   898
		}
sl@0
   899
	const TUint16 value = aPacket.iValue;
sl@0
   900
	if (value > 1)											// we support only one configuration
sl@0
   901
		{
sl@0
   902
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Configuration value too large: %d", value));
sl@0
   903
		return KErrGeneral;
sl@0
   904
		}
sl@0
   905
sl@0
   906
	__KTRACE_OPT(KUSB, Kern::Printf("  Configuration value: %d", value));
sl@0
   907
	ChangeConfiguration(value);
sl@0
   908
sl@0
   909
	// In 9.4.5 under GET_STATUS we read, that after SET_CONFIGURATION the HALT feature
sl@0
   910
	// for all endpoints is reset to zero.
sl@0
   911
	TInt num = 0;
sl@0
   912
	(TAny) DoForEveryEndpointInUse(&DUsbClientController::ClearHaltFeature, num);
sl@0
   913
	__KTRACE_OPT(KUSB, Kern::Printf("  Called ClearHaltFeature() for %d endpoints", num));
sl@0
   914
	SendEp0ZeroByteStatusPacket();							// success: zero bytes data during status stage
sl@0
   915
	return KErrNone;
sl@0
   916
	}
sl@0
   917
sl@0
   918
sl@0
   919
TInt DUsbClientController::ProcessGetInterface(const TUsbcSetup& aPacket)
sl@0
   920
	{
sl@0
   921
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetInterface()"));
sl@0
   922
	if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
sl@0
   923
		{
sl@0
   924
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   925
		return KErrGeneral;
sl@0
   926
		}
sl@0
   927
	if (iCurrentConfig == 0)
sl@0
   928
		{
sl@0
   929
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device not configured"));
sl@0
   930
		return KErrGeneral;
sl@0
   931
		}
sl@0
   932
	const TInt number = aPacket.iIndex;
sl@0
   933
	if (!InterfaceExists(number))
sl@0
   934
		{
sl@0
   935
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Bad interface index: %d", number));
sl@0
   936
		return KErrGeneral;
sl@0
   937
		}
sl@0
   938
	// Send alternate setting code of iCurrentInterface of Interface(set) <number> of the current
sl@0
   939
	// config (iCurrentConfig).
sl@0
   940
	const TUint8 setting = InterfaceNumber2InterfacePointer(number)->iCurrentInterface;
sl@0
   941
	__KTRACE_OPT(KUSB, Kern::Printf("  Reporting interface setting %d", setting));
sl@0
   942
	if (SetupEndpointZeroWrite(&setting, 1) == KErrNone)
sl@0
   943
		{
sl@0
   944
		iEp0WritePending = ETrue;
sl@0
   945
		}
sl@0
   946
	return KErrNone;
sl@0
   947
	}
sl@0
   948
sl@0
   949
sl@0
   950
TInt DUsbClientController::ProcessSetInterface(const TUsbcSetup& aPacket)
sl@0
   951
	{
sl@0
   952
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetInterface()"));
sl@0
   953
	if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
sl@0
   954
		{
sl@0
   955
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
   956
		return KErrGeneral;
sl@0
   957
		}
sl@0
   958
	if (iCurrentConfig == 0)
sl@0
   959
		{
sl@0
   960
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Device not configured"));
sl@0
   961
		return KErrGeneral;
sl@0
   962
		}
sl@0
   963
	const TInt number = aPacket.iIndex;
sl@0
   964
	if (!InterfaceExists(number))
sl@0
   965
		{
sl@0
   966
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Bad interface index: %d", number));
sl@0
   967
		return KErrGeneral;
sl@0
   968
		}
sl@0
   969
	const TInt setting = aPacket.iValue;
sl@0
   970
	TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(number);
sl@0
   971
	RPointerArray<TUsbcInterface>& ifcs = ifcset_ptr->iInterfaces;
sl@0
   972
	if (setting >= ifcs.Count())
sl@0
   973
		{
sl@0
   974
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Alt Setting >= bNumAltSettings: %d", setting));
sl@0
   975
		return KErrGeneral;
sl@0
   976
		}
sl@0
   977
	__KTRACE_OPT(KUSB, Kern::Printf("  Interface setting:: %d", setting));
sl@0
   978
	// Set iCurrentInterface of Interface(set) <number> of the current config
sl@0
   979
	// (iCurrentConfig) to alternate setting <setting>.
sl@0
   980
	ChangeInterface(ifcs[setting]);
sl@0
   981
	// In 9.4.5 under GET_STATUS we read, that after SET_INTERFACE the HALT feature
sl@0
   982
	// for all endpoints (of the now current interface setting) is reset to zero.
sl@0
   983
	RPointerArray<TUsbcLogicalEndpoint>& eps = ifcset_ptr->CurrentInterface()->iEndpoints;
sl@0
   984
	const TInt num_eps = eps.Count();
sl@0
   985
	for (TInt i = 0; i < num_eps; i++)
sl@0
   986
		{
sl@0
   987
		const TInt ep_num = EpAddr2Idx(eps[i]->iPEndpoint->iEndpointAddr);
sl@0
   988
		(TAny) ClearHaltFeature(ep_num);
sl@0
   989
		}
sl@0
   990
	SendEp0ZeroByteStatusPacket();							// success: zero bytes data during status stage
sl@0
   991
	return KErrNone;
sl@0
   992
	}
sl@0
   993
sl@0
   994
sl@0
   995
TInt DUsbClientController::ProcessSynchFrame(const TUsbcSetup& aPacket)
sl@0
   996
	{
sl@0
   997
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSynchFrame()"));
sl@0
   998
	if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured)
sl@0
   999
		{
sl@0
  1000
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid device state"));
sl@0
  1001
		return KErrGeneral;
sl@0
  1002
		}
sl@0
  1003
	const TInt ep = aPacket.iIndex;
sl@0
  1004
	if (EndpointExists(ep) == EFalse)
sl@0
  1005
		{
sl@0
  1006
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint does not exist"));
sl@0
  1007
		return KErrGeneral;
sl@0
  1008
		}
sl@0
  1009
	if (iRealEndpoints[EpAddr2Idx(ep)].iLEndpoint->iInfo.iType != KUsbEpTypeIsochronous)
sl@0
  1010
		{
sl@0
  1011
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint is not isochronous"));
sl@0
  1012
		return KErrGeneral;
sl@0
  1013
		}
sl@0
  1014
	// We always send 0:
sl@0
  1015
	*reinterpret_cast<TUint16*>(iEp0_TxBuf) = 0x00;
sl@0
  1016
	if (SetupEndpointZeroWrite(iEp0_TxBuf, 2) == KErrNone)
sl@0
  1017
		{
sl@0
  1018
		iEp0WritePending = ETrue;
sl@0
  1019
		}
sl@0
  1020
	return KErrNone;
sl@0
  1021
	}
sl@0
  1022
sl@0
  1023
sl@0
  1024
#ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
sl@0
  1025
void DUsbClientController::ProceedSetDescriptor()
sl@0
  1026
	{
sl@0
  1027
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProceedSetDescriptor()"));
sl@0
  1028
	// iEp0DataReceived already reflects the current buffer state
sl@0
  1029
	if (iEp0DataReceived < iSetup.iLength)
sl@0
  1030
		{
sl@0
  1031
		// Not yet all data received => proceed
sl@0
  1032
		return;
sl@0
  1033
		}
sl@0
  1034
	if (iEp0DataReceived > iSetup.iLength)
sl@0
  1035
		{
sl@0
  1036
		// Error: more data received than expected
sl@0
  1037
		// but we don't care...
sl@0
  1038
		}
sl@0
  1039
	// at this point: iEp0DataReceived == iSetup.iLength
sl@0
  1040
	const TUint8 type = HighByte(iSetup.iValue);
sl@0
  1041
	if (type == KUsbDescType_String)
sl@0
  1042
		{
sl@0
  1043
		// set/add new string descriptor
sl@0
  1044
		}
sl@0
  1045
	else
sl@0
  1046
		{
sl@0
  1047
		// set/add new ordinary descriptor
sl@0
  1048
		}
sl@0
  1049
	TUint8 index = LowByte(iSetup.iValue);
sl@0
  1050
	TUint16 langid = iSetup.iIndex;
sl@0
  1051
	TUint16 length_total = iSetup.iLength;
sl@0
  1052
	}
sl@0
  1053
#endif
sl@0
  1054
sl@0
  1055
sl@0
  1056
// --- Secondary (Helper) Functions
sl@0
  1057
sl@0
  1058
void DUsbClientController::SetClearHaltFeature(TInt aRealEndpoint, TUint8 aRequest)
sl@0
  1059
	{
sl@0
  1060
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetClearHaltFeature()"));
sl@0
  1061
	if (aRequest == KUsbRequest_SetFeature)
sl@0
  1062
		{
sl@0
  1063
		if (iRealEndpoints[aRealEndpoint].iHalt)
sl@0
  1064
			{
sl@0
  1065
			// (This condition is not really an error)
sl@0
  1066
			__KTRACE_OPT(KUSB, Kern::Printf("  Warning: HALT feature already set"));
sl@0
  1067
			return;
sl@0
  1068
			}
sl@0
  1069
		__KTRACE_OPT(KUSB, Kern::Printf("  setting HALT feature for real endpoint %d",
sl@0
  1070
										aRealEndpoint));
sl@0
  1071
		StallEndpoint(aRealEndpoint);
sl@0
  1072
		iRealEndpoints[aRealEndpoint].iHalt = ETrue;
sl@0
  1073
		}
sl@0
  1074
	else													// KUsbRequest_ClearFeature
sl@0
  1075
		{
sl@0
  1076
		if (iRealEndpoints[aRealEndpoint].iHalt == EFalse)
sl@0
  1077
			{
sl@0
  1078
			// In this case, before we return, the data toggles are reset to DATA0.
sl@0
  1079
			__KTRACE_OPT(KUSB, Kern::Printf("  Warning: HALT feature already cleared"));
sl@0
  1080
			ResetDataToggle(aRealEndpoint);
sl@0
  1081
			return;
sl@0
  1082
			}
sl@0
  1083
		__KTRACE_OPT(KUSB, Kern::Printf("  clearing HALT feature for real endpoint %d",
sl@0
  1084
										aRealEndpoint));
sl@0
  1085
		ResetDataToggle(aRealEndpoint);
sl@0
  1086
		ClearStallEndpoint(aRealEndpoint);
sl@0
  1087
		iRealEndpoints[aRealEndpoint].iHalt = EFalse;
sl@0
  1088
		}
sl@0
  1089
	EpStatusNotify(aRealEndpoint);							// only called if actually something changed
sl@0
  1090
	}
sl@0
  1091
sl@0
  1092
sl@0
  1093
TInt DUsbClientController::ClearHaltFeature(TInt aRealEndpoint)
sl@0
  1094
	{
sl@0
  1095
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ClearHaltFeature()"));
sl@0
  1096
	if (iRealEndpoints[aRealEndpoint].iHalt != EFalse)
sl@0
  1097
		{
sl@0
  1098
		ClearStallEndpoint(aRealEndpoint);
sl@0
  1099
		iRealEndpoints[aRealEndpoint].iHalt = EFalse;
sl@0
  1100
		}
sl@0
  1101
	return KErrNone;
sl@0
  1102
	}
sl@0
  1103
sl@0
  1104
sl@0
  1105
void DUsbClientController::ChangeConfiguration(TUint16 aValue)
sl@0
  1106
	{
sl@0
  1107
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ChangeConfiguration()"));
sl@0
  1108
	// New configuration is the same as the old one: 0
sl@0
  1109
	if (iCurrentConfig == 0 && aValue == 0)
sl@0
  1110
		{
sl@0
  1111
		// no-op
sl@0
  1112
		__KTRACE_OPT(KUSB, Kern::Printf("  Configuration: New == Old == 0 --> exiting"));
sl@0
  1113
		return;
sl@0
  1114
		}
sl@0
  1115
	// New configuration is the same as the old one (but not 0)
sl@0
  1116
	if (iCurrentConfig == aValue)
sl@0
  1117
		{
sl@0
  1118
		// no-op
sl@0
  1119
		__KTRACE_OPT(KUSB, Kern::Printf("  Configuration: New == Old == %d --> exiting", aValue));
sl@0
  1120
		return;
sl@0
  1121
		}
sl@0
  1122
	// Device is already configured
sl@0
  1123
	if (iCurrentConfig != 0)
sl@0
  1124
		{
sl@0
  1125
		__KTRACE_OPT(KUSB, Kern::Printf("  Device was configured: %d", iCurrentConfig));
sl@0
  1126
		// Tear down all interface(set)s of the old configuration
sl@0
  1127
		RPointerArray<TUsbcInterfaceSet>& ifcsets = CurrentConfig()->iInterfaceSets;
sl@0
  1128
		for (TInt i = 0; i < ifcsets.Count(); ++i)
sl@0
  1129
			{
sl@0
  1130
			__KTRACE_OPT(KUSB, Kern::Printf("  Tearing down InterfaceSet %d", i));
sl@0
  1131
			InterfaceSetTeardown(ifcsets[i]);
sl@0
  1132
			}
sl@0
  1133
		iCurrentConfig = 0;
sl@0
  1134
		// Enter Address state (from Configured)
sl@0
  1135
		if (iDeviceState == EUsbcDeviceStateConfigured)
sl@0
  1136
			NextDeviceState(EUsbcDeviceStateAddress);
sl@0
  1137
		}
sl@0
  1138
	// Device gets a new configuration
sl@0
  1139
	if (aValue != 0)
sl@0
  1140
		{
sl@0
  1141
		__KTRACE_OPT(KUSB, Kern::Printf("  Device gets new configuration..."));
sl@0
  1142
		// Setup all alternate settings 0 of all interfaces
sl@0
  1143
		// (Don't separate the next two lines of code.)
sl@0
  1144
		iCurrentConfig = aValue;
sl@0
  1145
		RPointerArray<TUsbcInterfaceSet>& ifcsets = CurrentConfig()->iInterfaceSets;
sl@0
  1146
		const TInt n = ifcsets.Count();
sl@0
  1147
		for (TInt i = 0; i < n; ++i)
sl@0
  1148
			{
sl@0
  1149
			__KTRACE_OPT(KUSB, Kern::Printf("  Setting up InterfaceSet %d", i));
sl@0
  1150
			InterfaceSetup(ifcsets[i]->iInterfaces[0]);
sl@0
  1151
			}
sl@0
  1152
		// Enter Configured state (from Address or Configured)
sl@0
  1153
		NextDeviceState(EUsbcDeviceStateConfigured);
sl@0
  1154
		}
sl@0
  1155
	__KTRACE_OPT(KUSB, Kern::Printf("  New configuration: %d", iCurrentConfig));
sl@0
  1156
	return;
sl@0
  1157
	}
sl@0
  1158
sl@0
  1159
sl@0
  1160
void DUsbClientController::InterfaceSetup(TUsbcInterface* aIfc)
sl@0
  1161
	{
sl@0
  1162
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InterfaceSetup()"));
sl@0
  1163
	const TInt num_eps = aIfc->iEndpoints.Count();
sl@0
  1164
	for (TInt i = 0; i < num_eps; i++)
sl@0
  1165
		{
sl@0
  1166
		// Prepare this endpoint for I/O
sl@0
  1167
		TUsbcLogicalEndpoint* const ep = aIfc->iEndpoints[i];
sl@0
  1168
		// (TUsbcLogicalEndpoint's FS/HS endpoint sizes and interval values got
sl@0
  1169
		//  adjusted in its constructor.)
sl@0
  1170
		if (iHighSpeed)
sl@0
  1171
			{
sl@0
  1172
			__KTRACE_OPT(KUSB, Kern::Printf("  Setting Ep info size to %d (HS)", ep->iEpSize_Hs));
sl@0
  1173
			ep->iInfo.iSize = ep->iEpSize_Hs;
sl@0
  1174
			}
sl@0
  1175
		else
sl@0
  1176
			{
sl@0
  1177
			__KTRACE_OPT(KUSB, Kern::Printf("  Setting Ep info size to %d (FS)", ep->iEpSize_Fs));
sl@0
  1178
			ep->iInfo.iSize = ep->iEpSize_Fs;
sl@0
  1179
			}
sl@0
  1180
		const TInt idx = EpAddr2Idx(ep->iPEndpoint->iEndpointAddr);
sl@0
  1181
		if (ConfigureEndpoint(idx, ep->iInfo) != KErrNone)
sl@0
  1182
			{
sl@0
  1183
			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint %d configuration failed", idx));
sl@0
  1184
			continue;
sl@0
  1185
			}
sl@0
  1186
		// Should there be a problem with it then we could try resetting the ep
sl@0
  1187
		// data toggle at this point (or before the Configure) as well.
sl@0
  1188
		__KTRACE_OPT(KUSB, Kern::Printf("  Connecting real ep addr 0x%02x & logical ep #%d",
sl@0
  1189
										ep->iPEndpoint->iEndpointAddr, ep->iLEndpointNum));
sl@0
  1190
		ep->iPEndpoint->iLEndpoint = ep;
sl@0
  1191
		}
sl@0
  1192
	aIfc->iInterfaceSet->iCurrentInterface = aIfc->iSettingCode;
sl@0
  1193
	return;
sl@0
  1194
	}
sl@0
  1195
sl@0
  1196
sl@0
  1197
void DUsbClientController::InterfaceSetTeardown(TUsbcInterfaceSet* aIfcSet)
sl@0
  1198
	{
sl@0
  1199
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InterfaceSetTeardown()"));
sl@0
  1200
	if (aIfcSet->iInterfaces.Count() == 0)
sl@0
  1201
		{
sl@0
  1202
		__KTRACE_OPT(KUSB, Kern::Printf("  No interfaces exist - returning"));
sl@0
  1203
		return;
sl@0
  1204
		}
sl@0
  1205
	RPointerArray<TUsbcLogicalEndpoint>& eps = aIfcSet->CurrentInterface()->iEndpoints;
sl@0
  1206
	const TInt num_eps = eps.Count();
sl@0
  1207
	for (TInt i = 0; i < num_eps; i++)
sl@0
  1208
		{
sl@0
  1209
		TUsbcLogicalEndpoint* const ep = eps[i];
sl@0
  1210
		const TInt idx = EpAddr2Idx(ep->iPEndpoint->iEndpointAddr);
sl@0
  1211
sl@0
  1212
		CancelTransferRequests(idx);
sl@0
  1213
sl@0
  1214
		if (!ep->iPEndpoint->iLEndpoint)
sl@0
  1215
			{
sl@0
  1216
			__KTRACE_OPT(KUSB, Kern::Printf("  real ep %d not configured: skipping", idx));
sl@0
  1217
			continue;
sl@0
  1218
			}
sl@0
  1219
		if (ResetDataToggle(idx) != KErrNone)
sl@0
  1220
			{
sl@0
  1221
			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint %d data toggle reset failed", idx));
sl@0
  1222
			}
sl@0
  1223
		if (DeConfigureEndpoint(idx) != KErrNone)
sl@0
  1224
			{
sl@0
  1225
			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint %d de-configuration failed", idx));
sl@0
  1226
			}
sl@0
  1227
sl@0
  1228
		__KTRACE_OPT(KUSB, Kern::Printf("  disconnecting real ep & logical ep"));
sl@0
  1229
		ep->iPEndpoint->iLEndpoint = NULL;
sl@0
  1230
		}
sl@0
  1231
	if (aIfcSet->CurrentInterface() != 0)
sl@0
  1232
		{
sl@0
  1233
		__KTRACE_OPT(KUSB, Kern::Printf("  Resetting alternate interface setting to 0"));
sl@0
  1234
		aIfcSet->iCurrentInterface = 0;
sl@0
  1235
		}
sl@0
  1236
	return;
sl@0
  1237
	}
sl@0
  1238
sl@0
  1239
sl@0
  1240
void DUsbClientController::ChangeInterface(TUsbcInterface* aIfc)
sl@0
  1241
	{
sl@0
  1242
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ChangeInterface()"));
sl@0
  1243
	TUsbcInterfaceSet* ifcset = aIfc->iInterfaceSet;
sl@0
  1244
	const TUint8 setting = aIfc->iSettingCode;
sl@0
  1245
	if (ifcset->iCurrentInterface == setting)
sl@0
  1246
		{
sl@0
  1247
		__KTRACE_OPT(KUSB, Kern::Printf("  New Ifc == old Ifc: nothing to do"));
sl@0
  1248
		return;
sl@0
  1249
		}
sl@0
  1250
	__KTRACE_OPT(KUSB, Kern::Printf("  Setting new interface setting #%d", setting));
sl@0
  1251
	InterfaceSetTeardown(ifcset);
sl@0
  1252
	InterfaceSetup(aIfc);
sl@0
  1253
	StatusNotify(static_cast<TUsbcDeviceState>(KUsbAlternateSetting | setting), ifcset->iClientId);
sl@0
  1254
	}
sl@0
  1255
sl@0
  1256
sl@0
  1257
// aFunction gets called, successively, with the endpoint index of every ep in-use as its argument.
sl@0
  1258
// (BTW: The declaration "type (class::*name)(params)" makes <name> a "pointer to element function".)
sl@0
  1259
//
sl@0
  1260
TInt DUsbClientController::DoForEveryEndpointInUse(TInt (DUsbClientController::*aFunction)(TInt), TInt& aCount)
sl@0
  1261
	{
sl@0
  1262
	__KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DoForEveryEndpointInUse()"));
sl@0
  1263
	aCount = 0;
sl@0
  1264
	TUsbcConfiguration* const config = CurrentConfig();
sl@0
  1265
	if (!config)
sl@0
  1266
		{
sl@0
  1267
		__KTRACE_OPT(KUSB, Kern::Printf("  Device is not configured - returning"));
sl@0
  1268
		return KErrNone;
sl@0
  1269
		}
sl@0
  1270
	RPointerArray<TUsbcInterfaceSet>& ifcsets = config->iInterfaceSets;
sl@0
  1271
	const TInt num_ifcsets = ifcsets.Count();
sl@0
  1272
	for (TInt i = 0; i < num_ifcsets; i++)
sl@0
  1273
		{
sl@0
  1274
		RPointerArray<TUsbcLogicalEndpoint>& eps = ifcsets[i]->CurrentInterface()->iEndpoints;
sl@0
  1275
		const TInt num_eps = eps.Count();
sl@0
  1276
		for (TInt j = 0; j < num_eps; j++)
sl@0
  1277
			{
sl@0
  1278
			const TInt ep_num = EpAddr2Idx(eps[j]->iPEndpoint->iEndpointAddr);
sl@0
  1279
			const TInt result = (this->*aFunction)(ep_num);
sl@0
  1280
			++aCount;
sl@0
  1281
			if (result != KErrNone)
sl@0
  1282
				{
sl@0
  1283
				return result;
sl@0
  1284
				}
sl@0
  1285
			}
sl@0
  1286
		}
sl@0
  1287
	return KErrNone;
sl@0
  1288
	}
sl@0
  1289
sl@0
  1290
sl@0
  1291
// -eof-