os/kernelhwsrv/kernel/eka/drivers/usbcsc/d_usbcsc.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\usbcsc\d_usbcsc.cpp
sl@0
    15
// LDD for USB Device driver stack, using shared chunks:
sl@0
    16
// The channel object.
sl@0
    17
// 
sl@0
    18
//
sl@0
    19
sl@0
    20
/**
sl@0
    21
 @file d_usbcsc.cpp
sl@0
    22
 @internalTechnology
sl@0
    23
*/
sl@0
    24
sl@0
    25
#include <drivers/usbcsc.h>
sl@0
    26
#include "platform.h"
sl@0
    27
sl@0
    28
/*****************************************************************************\
sl@0
    29
*   DUsbcScLogDevice                                                          *
sl@0
    30
*                                                                             *
sl@0
    31
*   Inherits from DLogicalDevice, the USB Shared Chunk LDD factory class      *
sl@0
    32
*                                                                             *
sl@0
    33
\*****************************************************************************/
sl@0
    34
sl@0
    35
_LIT(KUsbScLddName, "Usbcsc");
sl@0
    36
sl@0
    37
static const TInt KUsbRequestCallbackPriority = 2;
sl@0
    38
sl@0
    39
/** Real entry point from the Kernel: return a new driver.
sl@0
    40
 */
sl@0
    41
DECLARE_STANDARD_LDD()
sl@0
    42
	{
sl@0
    43
	return new DUsbcScLogDevice;
sl@0
    44
	}
sl@0
    45
sl@0
    46
/** Create a channel on the device.
sl@0
    47
sl@0
    48
	@internalComponent
sl@0
    49
*/
sl@0
    50
TInt DUsbcScLogDevice::Create(DLogicalChannelBase*& aChannel)
sl@0
    51
	{
sl@0
    52
	aChannel = new DLddUsbcScChannel;
sl@0
    53
	return aChannel ? KErrNone : KErrNoMemory;
sl@0
    54
	}
sl@0
    55
sl@0
    56
sl@0
    57
DUsbcScLogDevice::DUsbcScLogDevice()
sl@0
    58
      {
sl@0
    59
	  iParseMask = KDeviceAllowUnit;
sl@0
    60
	  iUnitsMask = 0xffffffff;								// Leave units decision to the Controller
sl@0
    61
      iVersion = TVersion(KUsbcScMajorVersion, KUsbcScMinorVersion, KUsbcScBuildVersion);
sl@0
    62
      }
sl@0
    63
sl@0
    64
sl@0
    65
TInt DUsbcScLogDevice::Install()
sl@0
    66
	{
sl@0
    67
	// Only proceed if we have the Controller underneath us
sl@0
    68
	if (!DUsbClientController::UsbcControllerPointer())
sl@0
    69
		{
sl@0
    70
		__KTRACE_OPT(KPANIC, Kern::Printf("LDD Install: USB Controller Not Present"));
sl@0
    71
		return KErrGeneral;
sl@0
    72
		}
sl@0
    73
	return SetName(&KUsbScLddName);
sl@0
    74
	}
sl@0
    75
sl@0
    76
sl@0
    77
//
sl@0
    78
// Return the USB controller capabilities.
sl@0
    79
//
sl@0
    80
void DUsbcScLogDevice::GetCaps(TDes8& aDes) const
sl@0
    81
	{
sl@0
    82
	TPckgBuf<TCapsDevUsbc> b;
sl@0
    83
	b().version = iVersion;
sl@0
    84
	Kern::InfoCopy(aDes, b);
sl@0
    85
	}
sl@0
    86
sl@0
    87
// End DUsbcScLogDevice
sl@0
    88
sl@0
    89
/*****************************************************************************\
sl@0
    90
*   TUsbcScChunkInfo                                                          *
sl@0
    91
*                                                                             *
sl@0
    92
*   Where Chunk information is stored for the channel, and preseved for the   *
sl@0
    93
*   life of the chunk.                                                        *
sl@0
    94
*                                                                             *
sl@0
    95
\*****************************************************************************/
sl@0
    96
sl@0
    97
void DfcChunkCleanup(TAny*);
sl@0
    98
sl@0
    99
TUsbcScChunkInfo::TUsbcScChunkInfo(DLogicalDevice* aLdd)
sl@0
   100
	: 	iChunk(NULL),
sl@0
   101
		iCleanup((TDfcFn)&DfcChunkCleanup,this,Kern::SvMsgQue(),0),
sl@0
   102
		iChunkMem(NULL),
sl@0
   103
		iLdd(aLdd)
sl@0
   104
	{
sl@0
   105
	iPageNtz = (TInt8)__e32_find_ls1_32(Kern::RoundToPageSize(1));
sl@0
   106
	}
sl@0
   107
sl@0
   108
TInt TUsbcScChunkInfo::CreateChunk(TInt aTotalSize)
sl@0
   109
	{
sl@0
   110
	// First, reserve an TUint of memory for each of pages needed to hold aTotalSize of memory.
sl@0
   111
	// This will form the chunk map, so that we can look up the memory geometry.
sl@0
   112
	iAllocatedSize = (aTotalSize>>iPageNtz)*sizeof(TUint);
sl@0
   113
	iPhysicalMap = (TUint*) Kern::AllocZ(iAllocatedSize);
sl@0
   114
	TInt r;
sl@0
   115
	if (iPhysicalMap==NULL)
sl@0
   116
		r = KErrNoMemory;
sl@0
   117
	else
sl@0
   118
		{
sl@0
   119
		TChunkCreateInfo chunkInfo;
sl@0
   120
		chunkInfo.iType = TChunkCreateInfo::ESharedKernelMultiple;
sl@0
   121
		chunkInfo.iMaxSize = aTotalSize;
sl@0
   122
		chunkInfo.iMapAttr = EMapAttrCachedMax;
sl@0
   123
		chunkInfo.iOwnsMemory = EFalse;
sl@0
   124
		chunkInfo.iDestroyedDfc = &iCleanup;
sl@0
   125
sl@0
   126
		TLinAddr chunkMem;
sl@0
   127
		r = Kern::ChunkCreate(chunkInfo, iChunk, chunkMem, iChunkMapAttr);
sl@0
   128
		iChunkMem = (TInt8*) chunkMem;
sl@0
   129
		if (r==KErrNone)
sl@0
   130
			iLdd->Open();
sl@0
   131
		}
sl@0
   132
sl@0
   133
	return r;
sl@0
   134
}
sl@0
   135
sl@0
   136
sl@0
   137
// This method requests closing the chunk.
sl@0
   138
// Note that nothing may happen immediately, as something else may have the chunk open.
sl@0
   139
void TUsbcScChunkInfo::Close()
sl@0
   140
{
sl@0
   141
	Kern::ChunkClose(iChunk);	
sl@0
   142
}
sl@0
   143
sl@0
   144
sl@0
   145
TInt TUsbcScChunkInfo::ChunkAlloc(TInt aOffset, TInt aSize)
sl@0
   146
	{
sl@0
   147
	TUint pageMask = (~0)<<iPageNtz;
sl@0
   148
	TUint rleMask = ~pageMask;
sl@0
   149
	TUint pageSize = rleMask+1;
sl@0
   150
	TInt r;
sl@0
   151
	TLinAddr physAddr;
sl@0
   152
sl@0
   153
	__KTRACE_OPT(KUSB, Kern::Printf("::chunkalloc  AllocPhysicalRam aSize %d", aSize));
sl@0
   154
sl@0
   155
	r = Epoc::AllocPhysicalRam(aSize, physAddr);
sl@0
   156
	__KTRACE_OPT(KUSB, if (r!=KErrNone) Kern::Printf("::chunkalloc AllocPhysicalRam r=%d  (Error!)", r));
sl@0
   157
	if (r==KErrNone)
sl@0
   158
		{	
sl@0
   159
		__KTRACE_OPT(KUSB, Kern::Printf("::chunkalloc ChunkCommitPhysical iChunk 0x%x size(%d), aOffset 0x%x, aSize 0x%x phsAddr 0x%x",
sl@0
   160
																	 				iChunk, sizeof(DChunk), aOffset, aSize,physAddr ));
sl@0
   161
sl@0
   162
		r = Kern::ChunkCommitPhysical(iChunk, aOffset, aSize, physAddr);
sl@0
   163
		__KTRACE_OPT(KUSB, if (r!=KErrNone) Kern::Printf("::chunkalloc ChunkCommitPhysical r=%d  (Error!)", r));
sl@0
   164
sl@0
   165
		if (r!=KErrNone)
sl@0
   166
				Epoc::FreePhysicalRam(physAddr, aSize);
sl@0
   167
		else 
sl@0
   168
			{ // record physical address and length in physical map
sl@0
   169
			TInt rle;
sl@0
   170
			TInt i=0;
sl@0
   171
			for (rle=(aSize>>iPageNtz); rle>0; rle--, i++,physAddr+=pageSize) 
sl@0
   172
				{
sl@0
   173
				__KTRACE_OPT(KUSB, Kern::Printf("::phys offset 0x%x = 0x%x",
sl@0
   174
												(aOffset>>iPageNtz)+i,  (physAddr & pageMask) | ((rle>(TInt)rleMask)?(TInt)rleMask:rle)));
sl@0
   175
				iPhysicalMap[(aOffset>>iPageNtz)+i] = (physAddr & pageMask) | ((rle>(TInt)rleMask)?(TInt)rleMask:rle);
sl@0
   176
				}
sl@0
   177
			}
sl@0
   178
		}
sl@0
   179
	else if (r==KErrNoMemory)
sl@0
   180
		r = -KErrNoMemory;  // Semi-expected error.
sl@0
   181
	return r;
sl@0
   182
	}
sl@0
   183
sl@0
   184
/**
sl@0
   185
This method retrieves the physical address of a given offset into the Chunk, and returns
sl@0
   186
the length of contiguous physical memory from this point.
sl@0
   187
sl@0
   188
@param aOffset		the offset from the start of the chunk, to be queried.
sl@0
   189
@param aPhysical	a pointer to a TPhysAddr, to be filled with the physical
sl@0
   190
					address of the memory at the given offset.
sl@0
   191
sl@0
   192
@returns the length of contiguous physical memory from the given offset.
sl@0
   193
*/
sl@0
   194
sl@0
   195
TInt TUsbcScChunkInfo::GetPhysical(TInt aOffset, TPhysAddr* aPhysical)
sl@0
   196
	{
sl@0
   197
	// Use masks, to retrieve the two components from the physical map, we created of the memory.
sl@0
   198
	TUint pageMask = (~0)<<iPageNtz;
sl@0
   199
	TUint val =  iPhysicalMap[aOffset>>iPageNtz];
sl@0
   200
	*aPhysical=(val & pageMask)+(aOffset & ~pageMask);
sl@0
   201
	return ((val & ~pageMask)<<iPageNtz) -  (aOffset & ~pageMask);
sl@0
   202
	}
sl@0
   203
sl@0
   204
sl@0
   205
// DFC calls this fuction, which invokes the cleanup method.
sl@0
   206
sl@0
   207
void DfcChunkCleanup(TAny* aChunkInfo)
sl@0
   208
	{
sl@0
   209
	((TUsbcScChunkInfo*) aChunkInfo)->ChunkCleanup();
sl@0
   210
	}
sl@0
   211
sl@0
   212
sl@0
   213
void TUsbcScChunkInfo::ChunkCleanup()
sl@0
   214
{
sl@0
   215
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::ChunkCleanup()"));
sl@0
   216
	TUint physAddr;
sl@0
   217
	TInt length;
sl@0
   218
	TInt offset = 0;
sl@0
   219
	
sl@0
   220
	// The part of the field used for the physical page address.
sl@0
   221
	TUint pageMask = (~0)<<iPageNtz;
sl@0
   222
sl@0
   223
	// The part of the field used for the run length encoding, of the contiguous pages.
sl@0
   224
	TUint rleMask = ~pageMask;
sl@0
   225
	TInt records=(iAllocatedSize>>2);
sl@0
   226
sl@0
   227
	while (offset < records) 
sl@0
   228
		{
sl@0
   229
		physAddr = 	iPhysicalMap[offset] & pageMask;
sl@0
   230
		length = iPhysicalMap[offset] & rleMask;
sl@0
   231
sl@0
   232
		if (physAddr>0)	
sl@0
   233
			Epoc::FreePhysicalRam(physAddr, length);
sl@0
   234
sl@0
   235
		offset += (length>0)?length:1;
sl@0
   236
		}
sl@0
   237
	Kern::Free(iPhysicalMap);
sl@0
   238
sl@0
   239
	DLogicalDevice* ldd = iLdd;
sl@0
   240
	delete this;
sl@0
   241
	ldd->Close(NULL);
sl@0
   242
}
sl@0
   243
sl@0
   244
TInt TUsbcScChunkInfo::New(TUsbcScChunkInfo*& aChunk, TInt aSize, DLogicalDevice* aLdd)
sl@0
   245
{
sl@0
   246
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::New totalSize %d", aSize));
sl@0
   247
sl@0
   248
	aChunk = new TUsbcScChunkInfo(aLdd);
sl@0
   249
	if (aChunk==NULL)
sl@0
   250
		{
sl@0
   251
		return KErrNoMemory;
sl@0
   252
		}
sl@0
   253
					
sl@0
   254
	TInt r = aChunk->CreateChunk(aSize);
sl@0
   255
	if (r!=KErrNone)
sl@0
   256
		{
sl@0
   257
		delete aChunk;
sl@0
   258
		aChunk=NULL;
sl@0
   259
		return r;
sl@0
   260
		}
sl@0
   261
sl@0
   262
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::New Created at 0x%x",  aChunk->iChunkMem  ));
sl@0
   263
	return KErrNone;
sl@0
   264
}
sl@0
   265
sl@0
   266
// End TUsbcScChunkInfo
sl@0
   267
sl@0
   268
/*****************************************************************************\
sl@0
   269
*    TUsbcScBuffer                                                            *
sl@0
   270
*                                                                             *
sl@0
   271
*    Represents a buffer, within a chunk.  Each buffers can be used by        *
sl@0
   272
*    differt endpoint on differnt alt settings                                *
sl@0
   273
*                                                                             *
sl@0
   274
\*****************************************************************************/
sl@0
   275
sl@0
   276
sl@0
   277
TInt TUsbcScBuffer::Construct(TInt aDirection, DLddUsbcScChannel* aLdd, TInt aBufferOffset, TInt aBufferEndOffset, TInt aMinReadSize, TInt aMaxPacketSize, TInt aMaxReadSize)
sl@0
   278
	{
sl@0
   279
	TInt r;
sl@0
   280
#ifdef _DEBUG
sl@0
   281
	iSequence = aBufferOffset; // Initialized at this, so that each buffer starts with a diffrent sequence number
sl@0
   282
#endif
sl@0
   283
	iMinReadSize = aMinReadSize;
sl@0
   284
	TInt size = (aBufferEndOffset - aBufferOffset);
sl@0
   285
	TInt pageSize = Kern::RoundToPageSize(1);
sl@0
   286
	if (aMaxReadSize > 0)
sl@0
   287
		iMaxReadSize = aMaxReadSize;
sl@0
   288
	else
sl@0
   289
		iMaxReadSize = pageSize + ((size/3) & ~(pageSize -1));
sl@0
   290
	iLdd = aLdd;
sl@0
   291
	iDirection = aDirection;
sl@0
   292
	iMode=0;
sl@0
   293
	iChunkInfo = aLdd->iChunkInfo;
sl@0
   294
	iChunkAddr = (TLinAddr) (aLdd->iChunkInfo->iChunkMem);  //aChunkAddr;
sl@0
   295
sl@0
   296
	TInt headerSize =  sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
sl@0
   297
sl@0
   298
sl@0
   299
	TUint maxAlignment; // Note:  This is a mask for max Alignment, 
sl@0
   300
sl@0
   301
	if (aMaxPacketSize)
sl@0
   302
		{ // EP0 packets are not DMAed, and so dont need ialignment.
sl@0
   303
		iAlignMask = ~3;
sl@0
   304
		maxAlignment = 3;
sl@0
   305
		}
sl@0
   306
	else
sl@0
   307
		 maxAlignment = 1023; // We don't know what the alignment requirement will be until enumeration, so assume worse case.
sl@0
   308
sl@0
   309
	iFirstPacket = aBufferOffset + sizeof(SUsbcScBufferHeader) + headerSize;
sl@0
   310
	iFirstPacket = (iFirstPacket + maxAlignment) & ~maxAlignment;
sl@0
   311
	
sl@0
   312
	iBufferStart = (SUsbcScBufferHeader *) (iChunkAddr+aBufferOffset);
sl@0
   313
	iBufferEnd = aBufferEndOffset;
sl@0
   314
sl@0
   315
	if ((iDirection&1)==KUsbcScOut)
sl@0
   316
		iHead = iFirstPacket-headerSize;//aBufferOffset + sizeof(SUsbcScBufferHeader);
sl@0
   317
	else
sl@0
   318
		iSent = 0;
sl@0
   319
sl@0
   320
	iStalled=0;
sl@0
   321
	iMaxPacketSize=0;
sl@0
   322
	
sl@0
   323
	r =  iStatusList.Construct((aDirection==KUsbcScIn)?KUsbcScInRequests:KUsbcScOutRequests, iLdd->iClient);
sl@0
   324
	if (!r)
sl@0
   325
		{
sl@0
   326
		iMaxPacketSize = aMaxPacketSize; // Indicates configured if ep0, otherwise not.
sl@0
   327
		}
sl@0
   328
	return r;
sl@0
   329
	}
sl@0
   330
sl@0
   331
sl@0
   332
void TUsbcScBuffer::CreateChunkBufferHeader()
sl@0
   333
{
sl@0
   334
	if ((iDirection&1)==KUsbcScOut)
sl@0
   335
		{
sl@0
   336
		iBufferStart->iHead= iHead;
sl@0
   337
		iBufferStart->iTail= iHead; // Initially no data!
sl@0
   338
		iBufferStart->iBilTail=iHead;
sl@0
   339
		__KTRACE_OPT(KUSB, Kern::Printf("Realize:  iHead 0x%x  bufferHeader 0x%x", iHead,iBufferStart ));
sl@0
   340
sl@0
   341
		// Dont need to round here, as we will round it up on endpoint change. (configuration)
sl@0
   342
		}
sl@0
   343
}
sl@0
   344
sl@0
   345
/*
sl@0
   346
TUsbcScBuffer::StartEndpoint
sl@0
   347
sl@0
   348
This method sets the nessesary paramenters to the buffer, for use for a particular endpoint.
sl@0
   349
sl@0
   350
*/
sl@0
   351
void TUsbcScBuffer::StartEndpoint(TUsbcRequestCallback* aRequestInfo, TUint aFlags)
sl@0
   352
	{
sl@0
   353
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartEndpoint (0x%x) : ep %d(%d)",this,aRequestInfo->iEndpointNum, aRequestInfo->iRealEpNum));
sl@0
   354
	
sl@0
   355
	iCallback=aRequestInfo;
sl@0
   356
	iMaxPacketSize =  iLdd->iController->EndpointPacketSize(iLdd, aRequestInfo->iRealEpNum);
sl@0
   357
	iAlignMask = ~(((iMaxPacketSize+1) & 0xFFFFFFF8)-1);
sl@0
   358
	iMode = aFlags;
sl@0
   359
    __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartEndpoint : max Packets %d, mask 0x%x flags 0x%x", iMaxPacketSize, iAlignMask, iMode));
sl@0
   360
	if ((iDirection&1)==KUsbcScOut)
sl@0
   361
		{
sl@0
   362
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UsbcScOut\n"));
sl@0
   363
		// Add dummy packet (doesnt have to be aligned, which avoids what if it changes issue)
sl@0
   364
		// And Start next read.
sl@0
   365
		iNeedsPacket=KEpIsStarting;
sl@0
   366
		}
sl@0
   367
	}
sl@0
   368
sl@0
   369
sl@0
   370
sl@0
   371
void TUsbcScBuffer::Destroy()
sl@0
   372
{
sl@0
   373
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::Destroy()"));
sl@0
   374
	Cancel(KErrCancel);
sl@0
   375
	if (iLdd->iController && ((iDirection&1)==KUsbcScOut))  
sl@0
   376
		{  // Me must cancel reads to LDD to, an there will be no list for the callbacks to look into.
sl@0
   377
		iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
sl@0
   378
		}
sl@0
   379
	iStatusList.Destroy();
sl@0
   380
}
sl@0
   381
sl@0
   382
sl@0
   383
sl@0
   384
TInt TUsbcScBuffer::StartDataRead()
sl@0
   385
{
sl@0
   386
	if (!iMaxPacketSize)
sl@0
   387
	{
sl@0
   388
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Not Configured"));
sl@0
   389
		return KErrNone;
sl@0
   390
	}
sl@0
   391
	if (iStatusList.iState!=ENotRunning) 
sl@0
   392
		{
sl@0
   393
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Already Stated! (%d)",iStatusList.iState));
sl@0
   394
		return KErrNone;
sl@0
   395
		}
sl@0
   396
sl@0
   397
	TInt maxLength;
sl@0
   398
	TInt freeSpace;
sl@0
   399
	TPhysAddr physAddr;
sl@0
   400
sl@0
   401
	// get next request
sl@0
   402
	TUsbcScStatusElement* nextJob = iStatusList.Next();
sl@0
   403
	if (nextJob == NULL)
sl@0
   404
		{
sl@0
   405
		__KTRACE_OPT(KUSB, Kern::Printf("No more jobs"));
sl@0
   406
		if (iMode && KUsbScCoupledRead)
sl@0
   407
			return KErrEof;
sl@0
   408
		iStatusList.iState=EReadingAhead;
sl@0
   409
		}
sl@0
   410
	else
sl@0
   411
		iStatusList.iState=EInProgress;
sl@0
   412
sl@0
   413
	TInt tail = iBufferStart->iTail;
sl@0
   414
	TInt headerSize =  sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
sl@0
   415
	maxLength = iChunkInfo->GetPhysical(iHead + headerSize, &physAddr); //returns all the bytes available after iHead + headerSize)
sl@0
   416
sl@0
   417
	__ASSERT_DEBUG(maxLength>0,Kern::Fault("TUsbcScBuffer::StartDataRead(", __LINE__)); 
sl@0
   418
sl@0
   419
sl@0
   420
	if (tail>iHead)  //  # # # H _ _ _ T # # # #
sl@0
   421
		{
sl@0
   422
		__KTRACE_OPT(KUSB,Kern::Printf("TUsbcScBuffer::StartDataRead() - tail 0x%x>head 0x%x, maxlength 0x%x", tail, iHead, maxLength));
sl@0
   423
sl@0
   424
		freeSpace = (tail & iAlignMask) - (iHead +headerSize + (~iAlignMask+1) );  // Cant read right up to last buffer, or head/tail will cross.
sl@0
   425
sl@0
   426
		if (freeSpace<iMinReadSize)
sl@0
   427
			{
sl@0
   428
			iStatusList.iState=ENotRunning;
sl@0
   429
			__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataRead() - Stall!!"));
sl@0
   430
			return KErrOverflow; 				// Read STALL !! !! !!
sl@0
   431
			}
sl@0
   432
sl@0
   433
		if (freeSpace<maxLength)
sl@0
   434
			maxLength = freeSpace;
sl@0
   435
		}
sl@0
   436
	if (maxLength> iMaxReadSize) 
sl@0
   437
		maxLength =  iMaxReadSize;
sl@0
   438
	// else  tail<iHead (or empty)      _ _ _ T # # # H _ _ _ _
sl@0
   439
	// We would not have set iHead here if too small. So must be ok.
sl@0
   440
		
sl@0
   441
	__ASSERT_DEBUG(maxLength>=iMinReadSize,Kern::Fault("TUsbcScBuffer::StartDataRead(", __LINE__)); 
sl@0
   442
sl@0
   443
	TUint8* data = ((TUsbcScTransferHeader *) (iHead + iChunkAddr))->iData.b;
sl@0
   444
	// set up callback stucture
sl@0
   445
sl@0
   446
	iCallback->SetRxBufferInfo(data, physAddr, iIndexArray, iSizeArray,maxLength);
sl@0
   447
	TInt r;
sl@0
   448
	// Go!!
sl@0
   449
	r = iLdd->iController->SetupReadBuffer(*iCallback);
sl@0
   450
	if (r!=KErrNone)
sl@0
   451
		{
sl@0
   452
		__KTRACE_OPT(KUSB,Kern::Printf("SetupReadBuffer Error: %d, RT %d",r, iStatusList.iState));
sl@0
   453
		iStatusList.Complete(r);
sl@0
   454
		}
sl@0
   455
	// After this, TUsbcScEndpoint::RequestCallback is called in a DFC.
sl@0
   456
	// This in turn calls either TUsbcScBuffer::CompleteRead.
sl@0
   457
	return KErrNone;
sl@0
   458
}
sl@0
   459
sl@0
   460
sl@0
   461
void TUsbcScBuffer::CompleteRead(TBool aStartNextRead)
sl@0
   462
{
sl@0
   463
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::CompleteRead buff=%x",this));
sl@0
   464
sl@0
   465
    // The first packet always contains the total #of bytes
sl@0
   466
	const TInt byteCount = iCallback->iPacketSize[0];
sl@0
   467
	const TInt packetCount = iCallback->iRxPackets;
sl@0
   468
 	iCallback->iRxPackets=0;
sl@0
   469
	TUint flags = 0;
sl@0
   470
sl@0
   471
	if (iCallback->iPacketSize[packetCount - 1] < (TUint) iMaxPacketSize)
sl@0
   472
		flags = KUsbcScShortPacket;
sl@0
   473
sl@0
   474
	UpdateBufferList(byteCount, flags, aStartNextRead);
sl@0
   475
}
sl@0
   476
sl@0
   477
sl@0
   478
// This method "submits" the current transfer, and starts off the next read.
sl@0
   479
sl@0
   480
void TUsbcScBuffer::UpdateBufferList(TInt aByteCount,TUint aFlags, TBool aStartNextRead)
sl@0
   481
	{
sl@0
   482
sl@0
   483
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst aByteCount %d, flags 0x%x iHead 0x%x", aByteCount, aFlags, iHead));
sl@0
   484
sl@0
   485
	TInt headerSize =  sizeof(TUsbcScTransferHeader)-4; // TransferHeader includes 4 bytes of data.
sl@0
   486
	TLinAddr dummy;
sl@0
   487
	__KTRACE_OPT(KUSB, Kern::Printf("iHead 0x%x headerSize 0x%x",iHead, headerSize));
sl@0
   488
sl@0
   489
	// Find iNext
sl@0
   490
sl@0
   491
	TInt next =  iHead +  headerSize + aByteCount; // next unused byte in buffer.
sl@0
   492
	TInt maxLength; 
sl@0
   493
sl@0
   494
	// This may take a few loops before we settle on a value.
sl@0
   495
	do 
sl@0
   496
		{
sl@0
   497
		// round up.
sl@0
   498
		next = (next + headerSize + ~iAlignMask) & iAlignMask;
sl@0
   499
		maxLength = iChunkInfo->GetPhysical(next, &dummy);
sl@0
   500
sl@0
   501
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst  next %x  buffer end %x min-read: %x  maxRun %x", next, iBufferEnd, iMinReadSize, maxLength));
sl@0
   502
		// At the end of the buffer - wrap it if needbe.
sl@0
   503
		if ((TUint)(next + iMinReadSize) > iBufferEnd)
sl@0
   504
			{
sl@0
   505
			next = iFirstPacket;
sl@0
   506
			continue;
sl@0
   507
			}
sl@0
   508
		// Not enough space, move onto next block.
sl@0
   509
		if (maxLength<iMinReadSize) 
sl@0
   510
			{
sl@0
   511
			next+=maxLength;
sl@0
   512
			__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst Skip exhausted block. next %x max %d", next, maxLength));
sl@0
   513
			continue;
sl@0
   514
			}
sl@0
   515
		}
sl@0
   516
	while (EFalse);
sl@0
   517
sl@0
   518
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst next (pre deduct): %x, Fill in header at head: 0x%x,  BuffStart: 0x%x.", next, iHead, iBufferStart));
sl@0
   519
	
sl@0
   520
	next -=  headerSize;  // Move next back from the data start position, to the header start.
sl@0
   521
sl@0
   522
	TUsbcScTransferHeader* header = (TUsbcScTransferHeader*) (iHead + iChunkAddr);
sl@0
   523
	
sl@0
   524
// Create Header
sl@0
   525
#ifdef _DEBUG
sl@0
   526
	header->iHashId=59*(iLdd->iAlternateSetting+1)+iCallback->iRealEpNum; // Alt setting realated....
sl@0
   527
	header->iSequence=iSequence;
sl@0
   528
	iSequence++;
sl@0
   529
#endif
sl@0
   530
	header->iBytes=aByteCount;
sl@0
   531
	header->iNext=next;
sl@0
   532
	header->iAltSettingSeq=iLdd->iAsSeq;
sl@0
   533
	header->iAltSetting=iLdd->iAlternateSetting;
sl@0
   534
	header->iFlags=aFlags;
sl@0
   535
	__KTRACE_OPT(KUSB, Kern::Printf("We set next to 0x%x", next));
sl@0
   536
sl@0
   537
	iStatusList.iState=ENotRunning;
sl@0
   538
	if (next==iBufferStart->iTail) //or (othwise is as good as full)
sl@0
   539
		{
sl@0
   540
			iStalled=next;
sl@0
   541
		}
sl@0
   542
	else
sl@0
   543
		{
sl@0
   544
sl@0
   545
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst StartRead?? "));
sl@0
   546
		TInt oldHead=iHead;
sl@0
   547
		iHead = next;
sl@0
   548
sl@0
   549
		if ((aStartNextRead) && (StartDataRead() == KErrOverflow))
sl@0
   550
			{ // Oh crumbs, set state as slalled.
sl@0
   551
			if (oldHead != iBufferStart->iBilTail) 
sl@0
   552
				// If user has not read everything in the buffer
sl@0
   553
				// then set up a stall, so that ldd get to be woken early
sl@0
   554
				{
sl@0
   555
				iStalled=next;
sl@0
   556
				iHead=oldHead;
sl@0
   557
				}
sl@0
   558
			else // otherwise if everything is read
sl@0
   559
				// no choice but to return what we have
sl@0
   560
				{
sl@0
   561
				iBufferStart->iHead = iHead;
sl@0
   562
				}
sl@0
   563
			}
sl@0
   564
		else
sl@0
   565
			{
sl@0
   566
			iBufferStart->iHead = next;
sl@0
   567
			__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::UpdateBUfferLIst Compleating\n"));
sl@0
   568
			}
sl@0
   569
		// Complete userside
sl@0
   570
		iStatusList.Complete();
sl@0
   571
		}  
sl@0
   572
	}
sl@0
   573
sl@0
   574
void TUsbcScBuffer::PopStall()
sl@0
   575
	{
sl@0
   576
	if (iStalled==iBufferStart->iTail)
sl@0
   577
		return;  // Still stalled.
sl@0
   578
sl@0
   579
	if (iStalled!=-1) // If not Alt packet only stall
sl@0
   580
	{
sl@0
   581
		// pop off packet	
sl@0
   582
		iHead = iStalled;
sl@0
   583
 	}
sl@0
   584
	iStalled=0;
sl@0
   585
	// If Alt setting of the popped packet is different to now
sl@0
   586
	// Add alt setting change packet.
sl@0
   587
sl@0
   588
sl@0
   589
	if (StartDataRead() == KErrOverflow)
sl@0
   590
	{
sl@0
   591
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::PopStall Warning: Transfer was freed, but still no space!\n"));
sl@0
   592
	}
sl@0
   593
sl@0
   594
	iBufferStart->iHead = iHead;
sl@0
   595
	}
sl@0
   596
sl@0
   597
sl@0
   598
sl@0
   599
void TUsbcScBuffer::StartDataWrite()
sl@0
   600
	{
sl@0
   601
	
sl@0
   602
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite()"));
sl@0
   603
	TUsbcScStatusElement* nextJob = iStatusList.Next();
sl@0
   604
	TBool zlpReqd;
sl@0
   605
	TInt length;
sl@0
   606
	TUint start;
sl@0
   607
	TUint8* startAddr;
sl@0
   608
	TInt maxLength;
sl@0
   609
	TPhysAddr physAddr;
sl@0
   610
	TInt r;
sl@0
   611
	if (!iMaxPacketSize)
sl@0
   612
	{
sl@0
   613
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() - Not Configured"));
sl@0
   614
		return;
sl@0
   615
	}
sl@0
   616
sl@0
   617
	if (nextJob == NULL)
sl@0
   618
		{
sl@0
   619
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() - No more jobs d=%d", iDirection));
sl@0
   620
		if (iDirection==KUsbcScBiIn) // assume this is EP0, if this is true.
sl@0
   621
			{
sl@0
   622
			__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::StartDataWrite() Queue Read on EP0."));	
sl@0
   623
			// Start other read again.
sl@0
   624
			iLdd->iBuffers[iLdd->iEP0OutBuff].StartDataRead();
sl@0
   625
			}
sl@0
   626
		}
sl@0
   627
	else
sl@0
   628
		{
sl@0
   629
		if (iStatusList.iState==ENotRunning)
sl@0
   630
			iSent=0;
sl@0
   631
		iStatusList.iState=EInProgress;
sl@0
   632
sl@0
   633
		start = nextJob->iStart;
sl@0
   634
		startAddr = (TUint8*) (start + ((TUint) (iChunkInfo->iChunkMem)));
sl@0
   635
sl@0
   636
		length = nextJob->iLength;
sl@0
   637
		zlpReqd = (nextJob->iFlags & KUsbcScWriteFlagsZlp) !=0;
sl@0
   638
		// get max read length
sl@0
   639
		maxLength = iChunkInfo->GetPhysical( start, &physAddr); 
sl@0
   640
sl@0
   641
		if (maxLength < length)
sl@0
   642
			{
sl@0
   643
				// modify request.
sl@0
   644
				nextJob->iStart += maxLength;
sl@0
   645
				nextJob->iLength -= maxLength;
sl@0
   646
				// start this request.
sl@0
   647
				iStatusList.iState=EFramgementInProgress;
sl@0
   648
				zlpReqd=EFalse;
sl@0
   649
				length =  maxLength;
sl@0
   650
			}
sl@0
   651
sl@0
   652
		if (iDirection==KUsbcScBiIn) // this is for EP0
sl@0
   653
			{
sl@0
   654
			iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
sl@0
   655
			iLdd->iBuffers[iLdd->iEP0OutBuff].iStatusList.iState=ENotRunning;
sl@0
   656
			}
sl@0
   657
		
sl@0
   658
		iCallback->SetTxBufferInfo(startAddr, physAddr, length);
sl@0
   659
		iCallback->iZlpReqd = zlpReqd;
sl@0
   660
		r = iLdd->iController->SetupWriteBuffer(*iCallback);
sl@0
   661
		if (r!=KErrNone)
sl@0
   662
			{
sl@0
   663
			__KTRACE_OPT(KUSB, Kern::Printf("SetupWriteBUffer Error: %d",r));
sl@0
   664
			iStatusList.Complete(r);
sl@0
   665
			}
sl@0
   666
		}
sl@0
   667
sl@0
   668
	}
sl@0
   669
sl@0
   670
void TUsbcScBuffer::CompleteWrite()
sl@0
   671
	{
sl@0
   672
	TInt error = iCallback->iError;
sl@0
   673
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::CompleteWrite buff=%x, err=%d",this, error));
sl@0
   674
	iSent+= iCallback->iTxBytes;
sl@0
   675
sl@0
   676
	// More to send?
sl@0
   677
	if (error || iStatusList.iState!=EFramgementInProgress)
sl@0
   678
		{
sl@0
   679
		// complete request with error (if one).
sl@0
   680
		// Some data could have been transmitted, even with an error. 
sl@0
   681
		iStatusList.Complete(error);
sl@0
   682
		}
sl@0
   683
sl@0
   684
	// Start next request, or next part of this one.
sl@0
   685
	StartDataWrite();
sl@0
   686
	
sl@0
   687
	}
sl@0
   688
sl@0
   689
// Cancels the current request's callback.
sl@0
   690
// This is not to say it will cancel the actual operation,
sl@0
   691
// However it will cancel any further sections of the user perceived operation
sl@0
   692
// that are not yet started.
sl@0
   693
void TUsbcScBuffer::Cancel(TInt aErrorCode)
sl@0
   694
	{
sl@0
   695
	iStatusList.CancelQueued();
sl@0
   696
	if (iLdd->iController && ((iDirection&1)==KUsbcScIn))
sl@0
   697
		{
sl@0
   698
		iLdd->iController->CancelWriteBuffer(iLdd, iCallback->iRealEpNum);
sl@0
   699
		}
sl@0
   700
sl@0
   701
	iStatusList.Complete(aErrorCode);
sl@0
   702
	}
sl@0
   703
sl@0
   704
void TUsbcScBuffer::Ep0CancelLddRead()
sl@0
   705
	{
sl@0
   706
	// Stopping a read isn't as easy as one might think.
sl@0
   707
	// We cancel the callback, but then check if any data was received (but not returned to us).
sl@0
   708
	// If so, we must de-queue the request, and call the completion code.
sl@0
   709
	
sl@0
   710
	iLdd->iController->CancelReadBuffer(iLdd, iCallback->iRealEpNum);
sl@0
   711
	if (iCallback->iRxPackets) // received data?
sl@0
   712
		{
sl@0
   713
		// remove DFC (if infact sent)
sl@0
   714
		iCallback->iDfc.Cancel();
sl@0
   715
sl@0
   716
		// process the callback now, but dont start another
sl@0
   717
		CompleteRead(EFalse);
sl@0
   718
		}
sl@0
   719
	}
sl@0
   720
sl@0
   721
void TUsbcScBuffer::SendEp0StatusPacket(TInt aState)
sl@0
   722
{
sl@0
   723
	__KTRACE_OPT(KUSB, Kern::Printf(" TUsbcScBuffer::SendEp0StatusPacket(%d)", aState));
sl@0
   724
sl@0
   725
	// We need to add a packet to the buffer, so we must stop the pending read, and start
sl@0
   726
	// another after we have added out packet.  
sl@0
   727
	Ep0CancelLddRead();
sl@0
   728
sl@0
   729
	TUint* state = ((TUsbcScTransferHeader *) (iHead + iChunkAddr))->iData.i;
sl@0
   730
	*state = aState;
sl@0
   731
	UpdateBufferList(4,KUsbcScStateChange);
sl@0
   732
}
sl@0
   733
sl@0
   734
// End TUsbcScBuffer
sl@0
   735
sl@0
   736
/*****************************************************************************\
sl@0
   737
*    TUsbcScStatusList                                                        *
sl@0
   738
*                                                                             *
sl@0
   739
*    This is a list of read or write requests, containing user status         *
sl@0
   740
*    requests, that should later be completed.                                *
sl@0
   741
*                                                                             *
sl@0
   742
\*****************************************************************************/
sl@0
   743
sl@0
   744
/**
sl@0
   745
Constructor for TUsbcScStatusList.
sl@0
   746
sl@0
   747
@param aSize	is the number of requests to allow at any one time.  This value
sl@0
   748
				must be a power of two, for correct operation.
sl@0
   749
sl@0
   750
@returns KErrNoMemory if memory allocation failure, otherwise KErrNone.
sl@0
   751
*/
sl@0
   752
sl@0
   753
TInt TUsbcScStatusList::Construct(TInt aSize, DThread* aClient)
sl@0
   754
	{
sl@0
   755
	iSize=aSize;
sl@0
   756
	iHead = 0;
sl@0
   757
	iLength = 0;
sl@0
   758
	iClient = aClient;
sl@0
   759
	iElements=(TUsbcScStatusElement *) Kern::AllocZ(sizeof(TUsbcScStatusElement)*aSize);
sl@0
   760
	return (iElements==NULL)?KErrNoMemory:KErrNone;	
sl@0
   761
	};
sl@0
   762
sl@0
   763
sl@0
   764
// StatusList must be inactive before destroying.
sl@0
   765
void TUsbcScStatusList::Destroy()
sl@0
   766
	{
sl@0
   767
	if (iState!=ENotRunning)
sl@0
   768
		Kern::Fault("TUsbcScStatusList::Destroy", __LINE__);
sl@0
   769
	if (iElements)
sl@0
   770
		{
sl@0
   771
		Kern::Free(iElements);	
sl@0
   772
		iElements=NULL;
sl@0
   773
		}
sl@0
   774
	iClient=NULL;
sl@0
   775
}
sl@0
   776
sl@0
   777
void TUsbcScStatusList::Pop()
sl@0
   778
	{
sl@0
   779
	if (iLength>0)
sl@0
   780
		{
sl@0
   781
		iLength--;
sl@0
   782
		iHead = ((iHead+1) & (iSize-1));
sl@0
   783
		}
sl@0
   784
	}
sl@0
   785
sl@0
   786
TUsbcScStatusElement* TUsbcScStatusList::Next()
sl@0
   787
	{
sl@0
   788
	return (iLength==0)?NULL:&(iElements[iHead]);
sl@0
   789
	}
sl@0
   790
sl@0
   791
TInt TUsbcScStatusList ::Add(TRequestStatus* aStatus, TInt aLength, TUint aStart, TUint aFlags)
sl@0
   792
	{
sl@0
   793
	__KTRACE_OPT(KUSB,Kern::Printf("Adding request.  iLength %d  iSize %d", iLength, iSize));
sl@0
   794
	if (iLength<iSize)
sl@0
   795
		{
sl@0
   796
		TUsbcScStatusElement& e = iElements[((iHead+iLength) & (iSize-1))];
sl@0
   797
		e.iStatus = aStatus;
sl@0
   798
		e.iLength = aLength;
sl@0
   799
		e.iStart = aStart;
sl@0
   800
		e.iFlags = aFlags;
sl@0
   801
		iLength++;
sl@0
   802
		__KTRACE_OPT(KUSB,Kern::Printf("Adding request.  new iLength %d", iLength));
sl@0
   803
sl@0
   804
		return KErrNone;
sl@0
   805
		}
sl@0
   806
	else
sl@0
   807
		return KErrInUse;
sl@0
   808
	}
sl@0
   809
sl@0
   810
sl@0
   811
sl@0
   812
// This method cancels any requests that have yet to be started.
sl@0
   813
sl@0
   814
void TUsbcScStatusList::CancelQueued(TInt aError)
sl@0
   815
{
sl@0
   816
	if ((iLength==0) || ((iState!=ENotRunning) && (iLength==1)))  // Nothing to do.
sl@0
   817
		return;  
sl@0
   818
	TInt elements2Complete = iLength - (iState?1:0);
sl@0
   819
	TInt head = iHead;
sl@0
   820
	iLength = 0;
sl@0
   821
	if (iState)	// If (iState != ENotRunning), complete all elements excepting the one at head
sl@0
   822
		{
sl@0
   823
		head = ((head+1) & (iSize-1)); // To iterate through the queue
sl@0
   824
		iLength = 1;
sl@0
   825
		}
sl@0
   826
	// complete them all.
sl@0
   827
	for (; elements2Complete>0; elements2Complete--)
sl@0
   828
  		{
sl@0
   829
		Kern::RequestComplete(iClient, iElements[head].iStatus, aError);
sl@0
   830
		head = ((head+1) & (iSize-1)); 
sl@0
   831
  		}
sl@0
   832
	
sl@0
   833
}
sl@0
   834
sl@0
   835
sl@0
   836
/* This method Completes the head status request, and pops it from its list.
sl@0
   837
This version of Complete is to be used in cases where the next request is not
sl@0
   838
chained - usually because of an error.
sl@0
   839
sl@0
   840
@Param aError - the code to complete with.
sl@0
   841
sl@0
   842
returns KErrNotFound if there was no request to complete
sl@0
   843
*/
sl@0
   844
sl@0
   845
sl@0
   846
TInt TUsbcScStatusList::Complete(TInt aError)
sl@0
   847
	{
sl@0
   848
	if (iState==ENotRunning)
sl@0
   849
		{
sl@0
   850
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScStatusList::Complete() - iState == ENotRunning!"));
sl@0
   851
		}
sl@0
   852
 	else
sl@0
   853
		{
sl@0
   854
		iState=ENotRunning;
sl@0
   855
		if (iLength==0)
sl@0
   856
			return KErrNotFound;
sl@0
   857
sl@0
   858
		Kern::RequestComplete(iClient, iElements[iHead].iStatus, aError);
sl@0
   859
sl@0
   860
		iLength--;
sl@0
   861
		iHead = ((iHead+1) & (iSize-1));
sl@0
   862
		}
sl@0
   863
	return KErrNone;
sl@0
   864
	}
sl@0
   865
sl@0
   866
sl@0
   867
/* This method Completes the head status request, and pops it from its list. (If found.)
sl@0
   868
This version of Complete is to be used in cases where the request is successful, and
sl@0
   869
 next request after this has (if present) been chained.
sl@0
   870
*/
sl@0
   871
sl@0
   872
void TUsbcScStatusList::Complete()
sl@0
   873
	{
sl@0
   874
	if (iLength==0)
sl@0
   875
		return;
sl@0
   876
	__KTRACE_OPT(KUSB, Kern::Printf("Completing request.  iLength %d", iLength));
sl@0
   877
sl@0
   878
	Kern::RequestComplete(iClient, iElements[iHead].iStatus, KErrNone);
sl@0
   879
sl@0
   880
	iLength--;
sl@0
   881
	iHead = ((iHead+1) & (iSize-1));
sl@0
   882
	}
sl@0
   883
sl@0
   884
// End TUsbcScStatusList
sl@0
   885
sl@0
   886
/*****************************************************************************\
sl@0
   887
*   TRealizeInfo                                                              *
sl@0
   888
*                                                                             *
sl@0
   889
*   Used by DLddUsbcScChannel::RealizeInterface to set up the chunk           *
sl@0
   890
*                                                                             *
sl@0
   891
\*****************************************************************************/
sl@0
   892
sl@0
   893
// Init
sl@0
   894
//
sl@0
   895
// This method works out the number potential maximum number of endpoints
sl@0
   896
// and the number of alt settings.  With this information it allocs
sl@0
   897
// the necessary space for the given stucture to store information about
sl@0
   898
// the endpoints.  
sl@0
   899
// This is intended to be called by RealizeInterface.  This stucture is
sl@0
   900
// intended to be only temporary, and the space will be freed with Free()
sl@0
   901
// before RealizeInteface has finished.
sl@0
   902
sl@0
   903
void TRealizeInfo::Init(TUsbcScAlternateSettingList* aAlternateSettingList)
sl@0
   904
{
sl@0
   905
	iAlternateSettingList = aAlternateSettingList;
sl@0
   906
	iMaxEndpoints=0;
sl@0
   907
	iTotalSize   =0;
sl@0
   908
	iTotalBuffers=0;
sl@0
   909
	iAltSettings =0;
sl@0
   910
	__KTRACE_OPT(KUSB, Kern::Printf("Realize: work out max endpoint"));
sl@0
   911
	// Work out max endpoints and number of alternate settings.
sl@0
   912
sl@0
   913
	if (iAlternateSettingList)
sl@0
   914
		{
sl@0
   915
		TUsbcScAlternateSetting* alt = iAlternateSettingList->iHead;
sl@0
   916
		while (alt != NULL) 
sl@0
   917
			{
sl@0
   918
			iAltSettings++;
sl@0
   919
			if (alt->iNumberOfEndpoints>iMaxEndpoints)
sl@0
   920
				iMaxEndpoints = alt->iNumberOfEndpoints;
sl@0
   921
			// could work out in/out specifics, but unnecessary.
sl@0
   922
			alt = alt->iNext;
sl@0
   923
			};
sl@0
   924
		}
sl@0
   925
	
sl@0
   926
	// Alloc some temporary working space for temp endpoint metadata 
sl@0
   927
	__KTRACE_OPT(KUSB, Kern::Printf("Realize: Alloc temp.  Maxendpoints %d", iMaxEndpoints));
sl@0
   928
	TInt inout;
sl@0
   929
	for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
sl@0
   930
		{
sl@0
   931
		iBufs[inout].iEp = (TUsbcScEndpoint **) Kern::AllocZ(iAltSettings*iMaxEndpoints*sizeof(TUsbcScEndpoint *));
sl@0
   932
		iBufs[inout].iSizes = (TInt *) Kern::AllocZ(iMaxEndpoints*sizeof(TInt));
sl@0
   933
		}
sl@0
   934
}
sl@0
   935
sl@0
   936
// CopyAndSortEndpoints
sl@0
   937
//
sl@0
   938
// This method copies pointers to the endpoint records into TRealizeInfo
sl@0
   939
// such that they are sorted in order of size per alt setting.
sl@0
   940
// In and Out endpoints are separated, and kept separate.
sl@0
   941
// The provided data structure is assumed to have been initialised with
sl@0
   942
// Realize_InitRealizeInfo. 
sl@0
   943
//
sl@0
   944
// Return KErrArgument if the direction field is neither In or Out.
sl@0
   945
//
sl@0
   946
sl@0
   947
TInt TRealizeInfo::CopyAndSortEndpoints()
sl@0
   948
	{
sl@0
   949
	__KTRACE_OPT(KUSB, Kern::Printf("Realize: copy And sort"));
sl@0
   950
sl@0
   951
	TInt altSetting = 0;
sl@0
   952
	TInt endpointOffs;
sl@0
   953
	TInt endpoint;
sl@0
   954
	TInt altEp;
sl@0
   955
	TInt inout;
sl@0
   956
	TBool placed;
sl@0
   957
	TUsbcScAlternateSetting* alt;
sl@0
   958
	TEndpointSortBufs* bufsd;
sl@0
   959
sl@0
   960
	if (iAlternateSettingList)
sl@0
   961
		{
sl@0
   962
		for (alt = iAlternateSettingList->iHead;alt!=NULL;alt = alt->iNext )
sl@0
   963
			{		
sl@0
   964
			__KTRACE_OPT(KUSB, Kern::Printf("Realize:   AlternateSetting %x", alt));
sl@0
   965
sl@0
   966
			iBufs[KUsbcScIn].iEps =0;
sl@0
   967
			iBufs[KUsbcScOut].iEps =0;
sl@0
   968
sl@0
   969
			// For alt setting, iterate eps
sl@0
   970
			for (altEp=1; altEp <= alt->iNumberOfEndpoints; altEp++)
sl@0
   971
				{
sl@0
   972
				__KTRACE_OPT(KUSB, Kern::Printf("Realize:     Endpoint to add: %d",altEp));
sl@0
   973
sl@0
   974
				TUsbcScEndpoint* nextEp = alt->iEndpoint[altEp];
sl@0
   975
sl@0
   976
				__KTRACE_OPT(KUSB, Kern::Printf("Realize:      ep Buffer Size: %d",nextEp->EndpointInfo()->iBufferSize));
sl@0
   977
				
sl@0
   978
				inout = (nextEp->EndpointInfo()->iDir==KUsbEpDirIn)?KUsbcScIn:
sl@0
   979
						(nextEp->EndpointInfo()->iDir==KUsbEpDirOut)?KUsbcScOut:KUsbcScUnknown;
sl@0
   980
				if (inout==KUsbcScUnknown)
sl@0
   981
					{
sl@0
   982
					__KTRACE_OPT(KUSB, Kern::Printf("Realize:     KUsbcScUnknown %x",nextEp->EndpointInfo()->iDir));
sl@0
   983
					return KErrArgument;
sl@0
   984
					}
sl@0
   985
sl@0
   986
				bufsd = &(iBufs[inout]);
sl@0
   987
				__KTRACE_OPT(KUSB, Kern::Printf("Realize:      ep direction: %x # endpoints %d", inout, bufsd->iEps));
sl@0
   988
sl@0
   989
sl@0
   990
				// find and position ep, and insert.
sl@0
   991
sl@0
   992
				if (bufsd->iEps==0) // First entry.
sl@0
   993
					{
sl@0
   994
					__KTRACE_OPT(KUSB, Kern::Printf("Realize:       Add first endpoint"));
sl@0
   995
					endpointOffs = altSetting*iMaxEndpoints;
sl@0
   996
					bufsd->iEp[endpointOffs] = nextEp;
sl@0
   997
					}
sl@0
   998
				else
sl@0
   999
					{
sl@0
  1000
					placed = EFalse;
sl@0
  1001
					// Move down the list, until we find the right place.
sl@0
  1002
					for (endpoint=bufsd->iEps-1; endpoint>-1; endpoint--)
sl@0
  1003
						{
sl@0
  1004
						endpointOffs = altSetting*iMaxEndpoints + endpoint;
sl@0
  1005
						if (bufsd->iEp[endpointOffs]->EndpointInfo()->iBufferSize < nextEp->EndpointInfo()->iBufferSize)
sl@0
  1006
							{
sl@0
  1007
							__KTRACE_OPT(KUSB, Kern::Printf("Realize:       Shift Endpoint %d", endpoint));
sl@0
  1008
		
sl@0
  1009
							bufsd->iEp[endpointOffs+1] = bufsd->iEp[endpointOffs];
sl@0
  1010
							}
sl@0
  1011
						else
sl@0
  1012
							{
sl@0
  1013
							__KTRACE_OPT(KUSB, Kern::Printf("Realize:       Insert After Endpoint %d", endpoint));
sl@0
  1014
sl@0
  1015
							bufsd->iEp[endpointOffs+1] = nextEp;
sl@0
  1016
							placed = ETrue;
sl@0
  1017
							break;
sl@0
  1018
							}
sl@0
  1019
						} // end for endpoint
sl@0
  1020
						if (!placed) // if we didn't place it, it must be the biggest so far, so goes at the top.
sl@0
  1021
							bufsd->iEp[0] = nextEp;
sl@0
  1022
					} // endif
sl@0
  1023
				bufsd->iEps++;			
sl@0
  1024
				} // for altEp
sl@0
  1025
				altSetting++;
sl@0
  1026
			} // for alt
sl@0
  1027
		}// if iAltsettingList
sl@0
  1028
	return KErrNone;
sl@0
  1029
	}
sl@0
  1030
sl@0
  1031
// CalcBuffSizes
sl@0
  1032
//
sl@0
  1033
// This works out the sizes of all the buffers, and stores the result in aBufInfo
sl@0
  1034
// based on the buffer information provided in the same structure.
sl@0
  1035
// Realize_CopyAndSortEndpoints is used to fill the structure with the informaition
sl@0
  1036
// required.
sl@0
  1037
sl@0
  1038
void TRealizeInfo::CalcBuffSizes()
sl@0
  1039
	{
sl@0
  1040
	__KTRACE_OPT(KUSB, Kern::Printf("Realize: Calculate Buffers"));
sl@0
  1041
sl@0
  1042
	TInt endpoint;
sl@0
  1043
	TInt inout;
sl@0
  1044
	TInt altSetting;
sl@0
  1045
	TUsbcScEndpoint* nextEp;
sl@0
  1046
	TInt bufferSize;
sl@0
  1047
	TEndpointSortBufs* bufsd;
sl@0
  1048
sl@0
  1049
	for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
sl@0
  1050
		{
sl@0
  1051
		__KTRACE_OPT(KUSB, Kern::Printf("Realize:   Direction: %d", inout));
sl@0
  1052
sl@0
  1053
sl@0
  1054
		bufsd = &(iBufs[inout]);
sl@0
  1055
		// for each row, ie, buffer, find largest buffer need.
sl@0
  1056
		for (endpoint=0; endpoint<iMaxEndpoints; endpoint++)
sl@0
  1057
			{
sl@0
  1058
			__KTRACE_OPT(KUSB, Kern::Printf("Realize:     endpoint %d", endpoint));
sl@0
  1059
			TInt bufMaxSize=0;
sl@0
  1060
			for (altSetting=0; altSetting< iAltSettings; altSetting++)
sl@0
  1061
				{
sl@0
  1062
				__KTRACE_OPT(KUSB, Kern::Printf("Realize:       altSetting %d", altSetting));
sl@0
  1063
				nextEp= bufsd->iEp[altSetting* iMaxEndpoints + endpoint];
sl@0
  1064
				if (nextEp!=NULL)
sl@0
  1065
					{
sl@0
  1066
					bufferSize = nextEp->EndpointInfo()->iBufferSize;
sl@0
  1067
					__KTRACE_OPT(KUSB, Kern::Printf("Realize:       comparing size %d", bufferSize));
sl@0
  1068
					if (bufferSize> bufMaxSize)
sl@0
  1069
						 bufMaxSize = bufferSize;
sl@0
  1070
					}
sl@0
  1071
				} // for altsetting
sl@0
  1072
			__KTRACE_OPT(KUSB, Kern::Printf("Realize:     bufMaxSize %d", bufMaxSize));
sl@0
  1073
			bufsd->iSizes[endpoint] = bufMaxSize;
sl@0
  1074
			if (bufMaxSize>0) 
sl@0
  1075
				{
sl@0
  1076
				iTotalSize += bufsd->iSizes[endpoint];
sl@0
  1077
				iTotalBuffers++;
sl@0
  1078
				}
sl@0
  1079
			} // for endpoint
sl@0
  1080
		} // for in/out	
sl@0
  1081
}
sl@0
  1082
sl@0
  1083
// Free
sl@0
  1084
//
sl@0
  1085
// Cleans up after Init()
sl@0
  1086
sl@0
  1087
void TRealizeInfo::Free()
sl@0
  1088
	{
sl@0
  1089
	TInt inout;
sl@0
  1090
	for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
sl@0
  1091
		{
sl@0
  1092
		Kern::Free(iBufs[inout].iEp);
sl@0
  1093
		Kern::Free(iBufs[inout].iSizes);
sl@0
  1094
		}
sl@0
  1095
	}
sl@0
  1096
sl@0
  1097
// End TRealizeInfo
sl@0
  1098
sl@0
  1099
sl@0
  1100
// LayoutChunkHeader
sl@0
  1101
//
sl@0
  1102
// Sets up some geometry for the chunk;
sl@0
  1103
sl@0
  1104
void TRealizeInfo::LayoutChunkHeader(TUsbcScChunkInfo* aChunkInfo)
sl@0
  1105
{ 
sl@0
  1106
	// First set up the indexes to the header structures.
sl@0
  1107
	TUsbcScChunkHdrOffs* chkHdr = (TUsbcScChunkHdrOffs*) aChunkInfo->iChunkMem;
sl@0
  1108
sl@0
  1109
	chkHdr->iBuffers = sizeof(TUsbcScChunkHdrOffs); // First struct just after this one.
sl@0
  1110
	iChunkStuct = (TUsbcScChunkBuffersHeader*) ( (TInt) aChunkInfo->iChunkMem + chkHdr->iBuffers);
sl@0
  1111
sl@0
  1112
	// Store number of buffers in chunk
sl@0
  1113
	iChunkStuct->iRecordSize = sizeof(TUsbcScBufferRecord);
sl@0
  1114
	iChunkStuct->iNumOfBufs=iTotalBuffers;
sl@0
  1115
sl@0
  1116
	iAltSettingsTbl = (TUsbcScChunkAltSettingHeader*) &(iChunkStuct->iBufferOffset[(iTotalBuffers+2)*sizeof(TUsbcScBufferRecord)]); // 2 extra for EP0 in and out.
sl@0
  1117
sl@0
  1118
	chkHdr->iAltSettings = (TUint) iAltSettingsTbl - (TUint) aChunkInfo->iChunkMem;
sl@0
  1119
sl@0
  1120
	iAltSettingsTbl->iEpRecordSize = sizeof(TUint);
sl@0
  1121
	iAltSettingsTbl->iNumOfAltSettings = iAltSettings;
sl@0
  1122
sl@0
  1123
sl@0
  1124
	TInt tableOffset  = (TUint) iAltSettingsTbl->iAltTableOffset - (TUint) aChunkInfo->iChunkMem + iAltSettings*sizeof(TInt);
sl@0
  1125
	__KTRACE_OPT(KUSB, Kern::Printf("Realize: table offset: 0x%x, altTble %x iChnkMem %x altSettings %x",tableOffset, iAltSettingsTbl, aChunkInfo->iChunkMem, iAltSettings ));
sl@0
  1126
sl@0
  1127
	__KTRACE_OPT(KUSB, Kern::Printf("Realize: populate chunk - create alt settings table"));
sl@0
  1128
sl@0
  1129
	// Create alt settings table.  Set each element of altsettings table, to each induivatual alt setting table.
sl@0
  1130
	// then fill in the number of endpoints for that alt setting, in the table.
sl@0
  1131
sl@0
  1132
	TInt* noEpForAlt;
sl@0
  1133
	TInt altSetting;
sl@0
  1134
	TUsbcScAlternateSetting* alt;
sl@0
  1135
	if (iAlternateSettingList)
sl@0
  1136
		{
sl@0
  1137
		alt = iAlternateSettingList->iHead;
sl@0
  1138
		for (altSetting=0; altSetting<iAltSettings; altSetting++) 
sl@0
  1139
			{
sl@0
  1140
				__KTRACE_OPT(KUSB, Kern::Printf("Realize:   altSetting %d, tableOffset %d", altSetting, tableOffset));
sl@0
  1141
sl@0
  1142
				iAltSettingsTbl->iAltTableOffset[altSetting] = tableOffset;
sl@0
  1143
				noEpForAlt = (TInt*) &aChunkInfo->iChunkMem[tableOffset];
sl@0
  1144
			 
sl@0
  1145
				*noEpForAlt = alt->iNumberOfEndpoints;  // Set NumberofEndpoints field in Altsetting table
sl@0
  1146
				tableOffset+= sizeof(TInt)+ alt->iNumberOfEndpoints*sizeof(TUsbcScHdrEndpointRecord);
sl@0
  1147
				alt = alt->iNext;
sl@0
  1148
			}
sl@0
  1149
		}		
sl@0
  1150
sl@0
  1151
} // end LayoutChunkHeader
sl@0
  1152
sl@0
  1153
sl@0
  1154
sl@0
  1155
/*****************************************************************************\
sl@0
  1156
*   DLddUsbcScChannel                                                         *
sl@0
  1157
*                                                                             *
sl@0
  1158
*   Inherits from DLogicalDevice, the USB Shared Chunk LDD factory class      *
sl@0
  1159
*                                                                             *
sl@0
  1160
\*****************************************************************************/
sl@0
  1161
sl@0
  1162
//
sl@0
  1163
// Constructor
sl@0
  1164
//
sl@0
  1165
DLddUsbcScChannel::DLddUsbcScChannel()
sl@0
  1166
	: iValidInterface(EFalse),
sl@0
  1167
	  iAlternateSettingList(NULL),
sl@0
  1168
	  iEndpoint(NULL),
sl@0
  1169
	  iCompleteAllCallbackInfo(this, DLddUsbcScChannel::EmergencyCompleteDfc, KUsbRequestCallbackPriority),
sl@0
  1170
	  iStatusChangePtr(NULL),
sl@0
  1171
	  iStatusCallbackInfo(this, DLddUsbcScChannel::StatusChangeCallback, KUsbRequestCallbackPriority),
sl@0
  1172
	  iEndpointStatusChangePtr(NULL),
sl@0
  1173
	  iEndpointStatusCallbackInfo(this, DLddUsbcScChannel::EndpointStatusChangeCallback,
sl@0
  1174
								  KUsbRequestCallbackPriority),
sl@0
  1175
      iOtgFeatureChangePtr(NULL),
sl@0
  1176
      iOtgFeatureCallbackInfo(this, DLddUsbcScChannel::OtgFeatureChangeCallback, KUsbRequestCallbackPriority),
sl@0
  1177
	  iNumberOfEndpoints(0),
sl@0
  1178
	  iDeviceState(EUsbcDeviceStateUndefined),
sl@0
  1179
	  iOwnsDeviceControl(EFalse),
sl@0
  1180
	  iAlternateSetting(0),
sl@0
  1181
	  iAsSeq(0),
sl@0
  1182
	  iStatusFifo(NULL),
sl@0
  1183
	  iUserKnowsAltSetting(ETrue),
sl@0
  1184
	  iDeviceStatusNeeded(EFalse),
sl@0
  1185
	  iChannelClosing(EFalse),
sl@0
  1186
	  iRealizeCalled(EFalse),
sl@0
  1187
	  iChunkInfo(NULL),
sl@0
  1188
	  iNumBuffers(-1),
sl@0
  1189
	  iBuffers(NULL),
sl@0
  1190
	  iEp0Endpoint(NULL)
sl@0
  1191
	{
sl@0
  1192
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DLddUsbcScChannel()"));
sl@0
  1193
	iClient = &Kern::CurrentThread();
sl@0
  1194
	iClient->Open();
sl@0
  1195
	for (TInt i = 1; i < KUsbcMaxRequests; i++)
sl@0
  1196
		{
sl@0
  1197
		iRequestStatus[i] = NULL;
sl@0
  1198
		}
sl@0
  1199
	}
sl@0
  1200
sl@0
  1201
sl@0
  1202
//
sl@0
  1203
// Destructor
sl@0
  1204
//
sl@0
  1205
sl@0
  1206
DLddUsbcScChannel::~DLddUsbcScChannel()
sl@0
  1207
	{
sl@0
  1208
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::~DLddUsbcScChannel()"));
sl@0
  1209
	if (iController)
sl@0
  1210
		{
sl@0
  1211
		iStatusCallbackInfo.Cancel();
sl@0
  1212
		iEndpointStatusCallbackInfo.Cancel();
sl@0
  1213
	    iOtgFeatureCallbackInfo.Cancel();
sl@0
  1214
        iCompleteAllCallbackInfo.Cancel();
sl@0
  1215
		DestroyAllInterfaces();
sl@0
  1216
		if (iOwnsDeviceControl)
sl@0
  1217
			{
sl@0
  1218
			iController->ReleaseDeviceControl(this);
sl@0
  1219
			iOwnsDeviceControl = EFalse;
sl@0
  1220
			}
sl@0
  1221
		iController->DeRegisterClient(this);
sl@0
  1222
		iController=NULL;
sl@0
  1223
		DestroyEp0();
sl@0
  1224
		if (iStatusFifo!=NULL)
sl@0
  1225
			{
sl@0
  1226
			delete iStatusFifo;
sl@0
  1227
			}
sl@0
  1228
		}
sl@0
  1229
	__KTRACE_OPT(KUSB, Kern::Printf("Closing buffers"));
sl@0
  1230
	if (iBuffers)
sl@0
  1231
		{
sl@0
  1232
		TInt i;
sl@0
  1233
		for (i=0; i<(iNumBuffers+2); i++) 
sl@0
  1234
			{
sl@0
  1235
			iBuffers[i].Destroy();
sl@0
  1236
			}
sl@0
  1237
		Kern::Free(iBuffers);
sl@0
  1238
		}
sl@0
  1239
sl@0
  1240
	if (iRealizeCalled)
sl@0
  1241
		{
sl@0
  1242
		// Close Chunk
sl@0
  1243
		iChunkInfo->Close();
sl@0
  1244
		// ChunkInfo will delete itself with DFC, but the pointer here is no longer needed.		
sl@0
  1245
		iChunkInfo=NULL;
sl@0
  1246
		}
sl@0
  1247
	__KTRACE_OPT(KUSB, Kern::Printf("about to SafeClose"));
sl@0
  1248
	Kern::SafeClose((DObject*&)iClient, NULL);
sl@0
  1249
	}
sl@0
  1250
sl@0
  1251
sl@0
  1252
//
sl@0
  1253
// DoCreate - Create channel
sl@0
  1254
//
sl@0
  1255
sl@0
  1256
TInt DLddUsbcScChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
sl@0
  1257
	{
sl@0
  1258
	__KTRACE_OPT(KUSB, Kern::Printf("LDD DoCreateL 1 Ver = %02d %02d %02d",
sl@0
  1259
									aVer.iMajor, aVer.iMinor, aVer.iBuild));
sl@0
  1260
	if (!Kern::CurrentThreadHasCapability(ECapabilityCommDD,
sl@0
  1261
										  __PLATSEC_DIAGNOSTIC_STRING("Checked by USBCSC.LDD (USB Driver)")))
sl@0
  1262
		{
sl@0
  1263
		return KErrPermissionDenied;
sl@0
  1264
		}
sl@0
  1265
sl@0
  1266
	iController = DUsbClientController::UsbcControllerPointer();
sl@0
  1267
sl@0
  1268
	if (!iController)
sl@0
  1269
		{
sl@0
  1270
		return KErrGeneral;
sl@0
  1271
		}
sl@0
  1272
sl@0
  1273
	iStatusFifo = new TUsbcDeviceStatusQueue;
sl@0
  1274
	if (iStatusFifo == NULL)
sl@0
  1275
		{
sl@0
  1276
		return KErrNoMemory;
sl@0
  1277
		}
sl@0
  1278
sl@0
  1279
  	if (!Kern::QueryVersionSupported(TVersion(KUsbcScMajorVersion, KUsbcScMinorVersion, KUsbcScBuildVersion), aVer))
sl@0
  1280
		{
sl@0
  1281
		return KErrNotSupported;
sl@0
  1282
		}
sl@0
  1283
sl@0
  1284
	// set up the correct DFC queue
sl@0
  1285
	SetDfcQ(iController->DfcQ(0));							// sets the channel's dfc queue
sl@0
  1286
    iCompleteAllCallbackInfo.SetDfcQ(iDfcQ);
sl@0
  1287
	iStatusCallbackInfo.SetDfcQ(iDfcQ);						// use the channel's dfcq for this dfc
sl@0
  1288
	iEndpointStatusCallbackInfo.SetDfcQ(iDfcQ);				// use the channel's dfcq for this dfc
sl@0
  1289
	iOtgFeatureCallbackInfo.SetDfcQ(iDfcQ);
sl@0
  1290
	iMsgQ.Receive();										//start up the message q
sl@0
  1291
	TInt r = iController->RegisterClientCallback(iCompleteAllCallbackInfo);
sl@0
  1292
	if (r != KErrNone)
sl@0
  1293
		return r;
sl@0
  1294
	r = iController->RegisterForStatusChange(iStatusCallbackInfo);
sl@0
  1295
	if (r != KErrNone)
sl@0
  1296
		return r;
sl@0
  1297
	r = iController->RegisterForEndpointStatusChange(iEndpointStatusCallbackInfo);
sl@0
  1298
	if (r != KErrNone)
sl@0
  1299
		return r;
sl@0
  1300
	r = iController->RegisterForOtgFeatureChange(iOtgFeatureCallbackInfo);
sl@0
  1301
	if (r != KErrNone)
sl@0
  1302
		return r;
sl@0
  1303
sl@0
  1304
	return r;
sl@0
  1305
	}
sl@0
  1306
// end DoCreate.
sl@0
  1307
sl@0
  1308
sl@0
  1309
//
sl@0
  1310
// HandleMsg
sl@0
  1311
//
sl@0
  1312
// Events from userside arrive here, and delegated to either DoRequest, DoControl or DoCancel.
sl@0
  1313
//
sl@0
  1314
sl@0
  1315
void DLddUsbcScChannel::HandleMsg(TMessageBase* aMsg)
sl@0
  1316
	{
sl@0
  1317
	TThreadMessage& m = *(TThreadMessage*)aMsg;
sl@0
  1318
	TInt id = m.iValue;
sl@0
  1319
	__KTRACE_OPT(KUSB, Kern::Printf("HandleMsg 0x%x", id));
sl@0
  1320
sl@0
  1321
	if (id == (TInt) ECloseMsg)
sl@0
  1322
		{
sl@0
  1323
		iChannelClosing = ETrue;
sl@0
  1324
		m.Complete(KErrNone, EFalse);
sl@0
  1325
		return;
sl@0
  1326
		}
sl@0
  1327
sl@0
  1328
	TInt r;
sl@0
  1329
	if (id < 0)
sl@0
  1330
		{
sl@0
  1331
		// DoRequest
sl@0
  1332
		TRequestStatus* pS = (TRequestStatus*) m.Ptr0();
sl@0
  1333
		r = DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
sl@0
  1334
		m.Complete(r, ETrue);
sl@0
  1335
		}
sl@0
  1336
	else if (id & RDevUsbcScClient::ERequestCancel)
sl@0
  1337
		{
sl@0
  1338
		// DoCancel
sl@0
  1339
		r = DoCancel(id, (TUint) m.Ptr0(), (TUint) m.Ptr1());
sl@0
  1340
		m.Complete(r, ETrue);
sl@0
  1341
	}
sl@0
  1342
	else
sl@0
  1343
		{
sl@0
  1344
		// DoControl
sl@0
  1345
		r = DoControl(id, m.Ptr0(), m.Ptr1());
sl@0
  1346
		m.Complete(r, ETrue);
sl@0
  1347
		}
sl@0
  1348
	}
sl@0
  1349
// end HandleMsg.
sl@0
  1350
sl@0
  1351
sl@0
  1352
#define BREAK_IF_NULL_ARG(a,r) if (a==NULL) { r = KErrArgument; __KTRACE_OPT(KUSB,Kern::Printf("NULL Argument")); break; }
sl@0
  1353
sl@0
  1354
//
sl@0
  1355
// DoRequest - Asynchronous requests
sl@0
  1356
//
sl@0
  1357
// Overrides pure virtual, called by HandleMsg. (Above)
sl@0
  1358
//
sl@0
  1359
TInt DLddUsbcScChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
sl@0
  1360
	{
sl@0
  1361
	TInt reqNo = aReqNo & RDevUsbcScClient::KFieldIdMask;
sl@0
  1362
	TInt r = KErrNone;  // return via request notify
sl@0
  1363
	TBool needsCompletion =EFalse;
sl@0
  1364
sl@0
  1365
	__KTRACE_OPT(KUSB, Kern::Printf("DoRequest 0x%08x", aReqNo));
sl@0
  1366
sl@0
  1367
	if ((reqNo>RDevUsbcScClient::ERequestReadDataNotify) &&
sl@0
  1368
		(reqNo<RDevUsbcScClient::ERequestMaxRequests))
sl@0
  1369
		{
sl@0
  1370
		if (iRequestStatus[reqNo])
sl@0
  1371
			{
sl@0
  1372
			PanicClientThread(ERequestAlreadyPending);
sl@0
  1373
			return 0;
sl@0
  1374
			}
sl@0
  1375
		iRequestStatus[reqNo] = aStatus;
sl@0
  1376
		}
sl@0
  1377
sl@0
  1378
	switch (reqNo)
sl@0
  1379
		{
sl@0
  1380
	case RDevUsbcScClient::ERequestWriteData:
sl@0
  1381
		{
sl@0
  1382
		TInt buffer =  (aReqNo>>RDevUsbcScClient::KFieldBuffPos)&RDevUsbcScClient::KFieldBuffMask;
sl@0
  1383
		__KTRACE_OPT(KUSB, Kern::Printf("ERequestWriteData"));
sl@0
  1384
		BREAK_IF_NULL_ARG(a2,r);
sl@0
  1385
sl@0
  1386
		r = DoWriteData( aStatus, buffer, (TInt) a1 /*Start*/, (TInt) a2 /* Length */,
sl@0
  1387
						 aReqNo>>RDevUsbcScClient::KFieldFlagsPos ); // Flags
sl@0
  1388
		break;
sl@0
  1389
		}
sl@0
  1390
	case RDevUsbcScClient::ERequestReadDataNotify:
sl@0
  1391
		{
sl@0
  1392
		__KTRACE_OPT(KUSB, Kern::Printf("ERequestReadDataNotify"));
sl@0
  1393
		return DoReadDataNotify(aStatus, (TInt) a1, (TInt) a2); // a1 = aBufferNumber, a2 - aLength;
sl@0
  1394
		} 
sl@0
  1395
sl@0
  1396
	case RDevUsbcScClient::ERequestAlternateDeviceStatusNotify:
sl@0
  1397
		{
sl@0
  1398
		__KTRACE_OPT(KUSB, Kern::Printf("ERequestAlternateDeviceStatusNotify"));
sl@0
  1399
		BREAK_IF_NULL_ARG(a1,r);
sl@0
  1400
		iDeviceStatusNeeded = ETrue;
sl@0
  1401
		iStatusChangePtr = a1;
sl@0
  1402
		needsCompletion = AlternateDeviceStateTestComplete();
sl@0
  1403
		break;
sl@0
  1404
		}
sl@0
  1405
	case RDevUsbcScClient::ERequestReEnumerate:
sl@0
  1406
		{
sl@0
  1407
		__KTRACE_OPT(KUSB, Kern::Printf("ERequestReEnumerate"));
sl@0
  1408
		// If successful, this will complete via the status notification.
sl@0
  1409
		r = iController->ReEnumerate();
sl@0
  1410
		break;
sl@0
  1411
		}
sl@0
  1412
	case RDevUsbcScClient::ERequestEndpointStatusNotify:
sl@0
  1413
		{
sl@0
  1414
		__KTRACE_OPT(KUSB, Kern::Printf("ERequestEndpointStatusNotify"));
sl@0
  1415
		BREAK_IF_NULL_ARG(a1,r);
sl@0
  1416
		
sl@0
  1417
		iEndpointStatusChangePtr = a1;
sl@0
  1418
		break;
sl@0
  1419
		}
sl@0
  1420
	case RDevUsbcScClient::ERequestOtgFeaturesNotify:
sl@0
  1421
		{
sl@0
  1422
		__KTRACE_OPT(KUSB, Kern::Printf("ERequestOtgFeaturesNotify"));
sl@0
  1423
		BREAK_IF_NULL_ARG(a1,r);
sl@0
  1424
			
sl@0
  1425
		iOtgFeatureChangePtr = a1;
sl@0
  1426
		break;
sl@0
  1427
		}
sl@0
  1428
    default:
sl@0
  1429
		r = KErrNotSupported;
sl@0
  1430
		}
sl@0
  1431
sl@0
  1432
	if ((needsCompletion) || (r != KErrNone))
sl@0
  1433
		{
sl@0
  1434
		iRequestStatus[reqNo] = aStatus;
sl@0
  1435
		Kern::RequestComplete(iClient, iRequestStatus[reqNo], r);
sl@0
  1436
		}
sl@0
  1437
	return KErrNone;
sl@0
  1438
	}
sl@0
  1439
// end DoRequest.
sl@0
  1440
sl@0
  1441
sl@0
  1442
//
sl@0
  1443
// DoReadDataNotify
sl@0
  1444
//
sl@0
  1445
// This method sets up the request to facilitate the userside being notifed when new data has been read.
sl@0
  1446
//
sl@0
  1447
TInt DLddUsbcScChannel::DoReadDataNotify(TRequestStatus* aStatus, TInt aBufferNum, TInt aLength)
sl@0
  1448
	{
sl@0
  1449
	__KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify(x, %d, 0x%x)", aBufferNum, aLength));
sl@0
  1450
	TInt r = KErrNone;
sl@0
  1451
	// check range
sl@0
  1452
	if ((aBufferNum<0) ||  (aBufferNum>=iNumBuffers))  // Indirectly checks that we are set up.
sl@0
  1453
		{
sl@0
  1454
		if (aBufferNum!=KUsbcScEndpointZero)
sl@0
  1455
			{
sl@0
  1456
	        __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify : Bad Buffer Number!"));
sl@0
  1457
			return KErrArgument;
sl@0
  1458
			}
sl@0
  1459
		else
sl@0
  1460
			{
sl@0
  1461
			aBufferNum = iEP0OutBuff;
sl@0
  1462
			}
sl@0
  1463
		}
sl@0
  1464
	else
sl@0
  1465
		{
sl@0
  1466
		// check direction
sl@0
  1467
		if (iBuffers[aBufferNum].iDirection!=KUsbcScOut)
sl@0
  1468
			{
sl@0
  1469
   		     __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify : Bad Buffer Direction!"));
sl@0
  1470
			return KErrNotSupported;
sl@0
  1471
			}
sl@0
  1472
		if (!Configured())
sl@0
  1473
			return KErrUsbInterfaceNotReady;
sl@0
  1474
		}
sl@0
  1475
	SUsbcScBufferHeader* scBuffer = (SUsbcScBufferHeader*) iBuffers[aBufferNum].iBufferStart;
sl@0
  1476
sl@0
  1477
	__KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoReadDataNotify  head %x tail %x", iBuffers[aBufferNum].iHead , scBuffer->iTail ));
sl@0
  1478
sl@0
  1479
	if (iBuffers[aBufferNum].iHead != scBuffer->iBilTail)
sl@0
  1480
		r = KErrCompletion;
sl@0
  1481
	else
sl@0
  1482
		if (iBuffers[aBufferNum].iStalled)
sl@0
  1483
			{
sl@0
  1484
			iBuffers[aBufferNum].PopStall();
sl@0
  1485
			return KErrCompletion;
sl@0
  1486
			}
sl@0
  1487
		else
sl@0
  1488
			r = iBuffers[aBufferNum].iStatusList.Add(aStatus, aLength, 0,0);
sl@0
  1489
sl@0
  1490
	if (iBuffers[aBufferNum].iStatusList.iState==ENotRunning)
sl@0
  1491
		{
sl@0
  1492
		iBuffers[aBufferNum].StartDataRead();
sl@0
  1493
		}
sl@0
  1494
	else
sl@0
  1495
		{
sl@0
  1496
		__KTRACE_OPT(KUSB, Kern::Printf("Job in Progress!"));
sl@0
  1497
		}
sl@0
  1498
	return r;
sl@0
  1499
	}
sl@0
  1500
// end DoReadDataNotify.
sl@0
  1501
sl@0
  1502
sl@0
  1503
sl@0
  1504
//
sl@0
  1505
// DoWriteData
sl@0
  1506
//
sl@0
  1507
// This method sets up the request to write data to USB from userside.
sl@0
  1508
//
sl@0
  1509
TInt DLddUsbcScChannel::DoWriteData(TRequestStatus* aStatus,TInt aBufferNum, TUint aStart, TUint aLength, TUint aFlags)
sl@0
  1510
	{
sl@0
  1511
	__KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData(%d, 0x%x, 0x%x, 0x%x)",  aBufferNum, aStart, aLength, aFlags));
sl@0
  1512
	if (!iUserKnowsAltSetting)
sl@0
  1513
		return KErrEof;
sl@0
  1514
	// Check Buffer Number
sl@0
  1515
	if ((aBufferNum<0) ||  (aBufferNum>=iNumBuffers))
sl@0
  1516
		{
sl@0
  1517
		if ((TUint)aBufferNum!=RDevUsbcScClient::KFieldBuffMask)  // KUsbcScEndpointZero & KFieldBuffMas = KFieldBuffMas;
sl@0
  1518
			{
sl@0
  1519
	        __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData : Bad Buffer Number!"));
sl@0
  1520
			return KErrArgument;
sl@0
  1521
			}
sl@0
  1522
		else
sl@0
  1523
			{
sl@0
  1524
			aBufferNum = iEP0InBuff;
sl@0
  1525
			}
sl@0
  1526
		}
sl@0
  1527
	else
sl@0
  1528
		{
sl@0
  1529
		// check direction
sl@0
  1530
		if (iBuffers[aBufferNum].iDirection!=KUsbcScIn)
sl@0
  1531
			{
sl@0
  1532
	    	    __KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData Bad endpoint Direction"));
sl@0
  1533
				return KErrArgument;
sl@0
  1534
			}
sl@0
  1535
		}
sl@0
  1536
sl@0
  1537
	TUsbcScBuffer& buf=iBuffers[aBufferNum];
sl@0
  1538
sl@0
  1539
	if ((aStart< (((TLinAddr) buf.iBufferStart)-buf.iChunkAddr)) || ((aStart+aLength)>iBuffers[aBufferNum].iBufferEnd))
sl@0
  1540
		{
sl@0
  1541
		__KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DoWriteData Bad Range aStart or aLength 0x%x > 0x%x + 0x%x < 0x%x", (((TLinAddr) buf.iBufferStart)-buf.iChunkAddr),aStart, aLength, iBuffers[aBufferNum].iBufferEnd ));
sl@0
  1542
		return KErrArgument;
sl@0
  1543
		}
sl@0
  1544
sl@0
  1545
	if ( (aBufferNum != iEP0InBuff) && !Configured())
sl@0
  1546
		return KErrUsbInterfaceNotReady;
sl@0
  1547
sl@0
  1548
	if (aStart & ~buf.iAlignMask)
sl@0
  1549
		{
sl@0
  1550
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScBuffer::DoDataWrite: address 0x%x unaligned.",aStart));
sl@0
  1551
		return KErrArgument;
sl@0
  1552
		}
sl@0
  1553
			
sl@0
  1554
	TInt r = iBuffers[aBufferNum].iStatusList.Add(aStatus, aLength, aStart, aFlags); //update
sl@0
  1555
sl@0
  1556
	if (iBuffers[aBufferNum].iStatusList.iState==ENotRunning)
sl@0
  1557
		{
sl@0
  1558
			iBuffers[aBufferNum].StartDataWrite();
sl@0
  1559
		}
sl@0
  1560
	else
sl@0
  1561
		{	
sl@0
  1562
		__KTRACE_OPT(KUSB, Kern::Printf("Job in Progress!"));
sl@0
  1563
		}
sl@0
  1564
sl@0
  1565
sl@0
  1566
	return r;
sl@0
  1567
	}
sl@0
  1568
// end DoWriteData.
sl@0
  1569
sl@0
  1570
sl@0
  1571
//
sl@0
  1572
// Cancel an outstanding request						// Cancel need reworking.
sl@0
  1573
//
sl@0
  1574
TInt DLddUsbcScChannel::DoCancel(TInt aReqNo, TUint aBuff, TUint aSpair)
sl@0
  1575
	{
sl@0
  1576
	TInt r = KErrNone;
sl@0
  1577
	TInt direction=KUsbcScOut;
sl@0
  1578
sl@0
  1579
	__KTRACE_OPT(KUSB, Kern::Printf("DoCancel: 0x%x aBuff 0x%x", aReqNo, aBuff));
sl@0
  1580
	switch (aReqNo)
sl@0
  1581
		{
sl@0
  1582
	case RDevUsbcScClient::ERequestCancel:
sl@0
  1583
		TInt buffer;
sl@0
  1584
		TInt mask;
sl@0
  1585
sl@0
  1586
		for (buffer=1, mask=1; buffer<iNumBuffers; buffer++,mask<<=1)
sl@0
  1587
			if (aBuff&mask)
sl@0
  1588
				iBuffers[buffer].Cancel(KErrCancel);
sl@0
  1589
sl@0
  1590
		return KErrNone;
sl@0
  1591
sl@0
  1592
	// coverity[missing_break]
sl@0
  1593
	case RDevUsbcScClient::ERequestWriteDataCancel:
sl@0
  1594
		direction = KUsbcScIn;
sl@0
  1595
	case RDevUsbcScClient::ERequestReadDataNotifyCancel:
sl@0
  1596
		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel Direction %d endpoints: 0x%x",direction, aReqNo));
sl@0
  1597
sl@0
  1598
		if (((TInt)aBuff)==KUsbcScEndpointZero) // EP0 is bi-directional, so pick correct buffer for call type
sl@0
  1599
			{
sl@0
  1600
			__KTRACE_OPT(KUSB, Kern::Printf("DoCancel Cancel Endpoint 0/%d",direction));
sl@0
  1601
			iEp0Endpoint->AbortTransfer();
sl@0
  1602
			if (direction==KUsbcScIn)
sl@0
  1603
				aBuff=iEP0InBuff;
sl@0
  1604
			else
sl@0
  1605
				aBuff=iEP0OutBuff;
sl@0
  1606
			} 
sl@0
  1607
		else if ((TInt)aBuff >= iNumBuffers) // check buff no range.
sl@0
  1608
			{
sl@0
  1609
			__KTRACE_OPT(KUSB, Kern::Printf("DoCancel Error: Bad buffer number"));
sl@0
  1610
			return KErrArgument;
sl@0
  1611
			}
sl@0
  1612
sl@0
  1613
		if ((iBuffers[aBuff].iDirection&1)!=direction) // Does direction match call type?
sl@0
  1614
			{
sl@0
  1615
			__KTRACE_OPT(KUSB, Kern::Printf("DoCancel Error: Bad buffer direction"));
sl@0
  1616
			return KErrArgument;
sl@0
  1617
			}	
sl@0
  1618
		iBuffers[aBuff].iStatusList.CancelQueued();
sl@0
  1619
		iBuffers[aBuff].Cancel(KErrCancel);
sl@0
  1620
		
sl@0
  1621
		return KErrNone;
sl@0
  1622
sl@0
  1623
	case RDevUsbcScClient::ERequestAlternateDeviceStatusNotifyCancel:
sl@0
  1624
		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel: ERequestAlternateDeviceStatusNotify 0x%x", aReqNo));
sl@0
  1625
		iDeviceStatusNeeded = EFalse;
sl@0
  1626
		iStatusFifo->FlushQueue();
sl@0
  1627
		if (iStatusChangePtr)
sl@0
  1628
			{
sl@0
  1629
			TInt deviceState = iController->GetDeviceStatus();
sl@0
  1630
			r = Kern::ThreadRawWrite(iClient, iStatusChangePtr, &deviceState, sizeof(deviceState), iClient);
sl@0
  1631
			if (r != KErrNone)
sl@0
  1632
				PanicClientThread(r);
sl@0
  1633
			iStatusChangePtr = NULL; 
sl@0
  1634
			}
sl@0
  1635
	break;
sl@0
  1636
sl@0
  1637
	case RDevUsbcScClient::ERequestReEnumerateCancel:
sl@0
  1638
		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestReEnumerate: 0x%x", aReqNo));
sl@0
  1639
	break;
sl@0
  1640
sl@0
  1641
	case RDevUsbcScClient::ERequestEndpointStatusNotifyCancel:
sl@0
  1642
		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestEndpointStatusNotify: 0x%x", aReqNo));
sl@0
  1643
		CancelNotifyEndpointStatus();
sl@0
  1644
	break;
sl@0
  1645
sl@0
  1646
 	case RDevUsbcScClient::ERequestOtgFeaturesNotifyCancel:
sl@0
  1647
		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestOtgFeaturesNotify: 0x%x", aReqNo));
sl@0
  1648
		CancelNotifyOtgFeatures();
sl@0
  1649
	break;
sl@0
  1650
sl@0
  1651
	default:
sl@0
  1652
		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel Unknown! 0x%x", aReqNo));
sl@0
  1653
		return KErrArgument;
sl@0
  1654
		}
sl@0
  1655
sl@0
  1656
	Kern::RequestComplete(iClient,iRequestStatus[aReqNo & ~RDevUsbcScClient::ERequestCancel], KErrCancel);
sl@0
  1657
	return r;
sl@0
  1658
	}
sl@0
  1659
sl@0
  1660
sl@0
  1661
void DLddUsbcScChannel::CancelNotifyEndpointStatus()
sl@0
  1662
	{
sl@0
  1663
	if (iEndpointStatusChangePtr)
sl@0
  1664
		{
sl@0
  1665
		TUint epBitmap = 0;
sl@0
  1666
		for (TInt i = 1; i <= iNumberOfEndpoints; i++)
sl@0
  1667
			{
sl@0
  1668
			TInt v = iController->GetEndpointStatus(this, iEndpoint[i]->RealEpNumber());
sl@0
  1669
			TUint b;
sl@0
  1670
			(v == EEndpointStateStalled) ? b = 1 : b = 0;
sl@0
  1671
			epBitmap |= b << i;
sl@0
  1672
			}
sl@0
  1673
		TInt r=Kern::ThreadRawWrite(iClient, iEndpointStatusChangePtr, (TUint8*) &epBitmap, sizeof(epBitmap), iClient);
sl@0
  1674
		if (r != KErrNone)
sl@0
  1675
			PanicClientThread(r);
sl@0
  1676
		iEndpointStatusChangePtr = NULL;
sl@0
  1677
		}
sl@0
  1678
	}
sl@0
  1679
sl@0
  1680
void DLddUsbcScChannel::CancelNotifyOtgFeatures()
sl@0
  1681
	{
sl@0
  1682
    if (iOtgFeatureChangePtr)
sl@0
  1683
        {
sl@0
  1684
        TUint8 features;
sl@0
  1685
        iController->GetCurrentOtgFeatures(features);
sl@0
  1686
		TInt r=Kern::ThreadRawWrite(iClient, iOtgFeatureChangePtr, (TUint8*)&features, sizeof(features), iClient);
sl@0
  1687
		if (r != KErrNone)
sl@0
  1688
			PanicClientThread(r);
sl@0
  1689
        iOtgFeatureChangePtr = NULL;
sl@0
  1690
        }
sl@0
  1691
    }
sl@0
  1692
sl@0
  1693
sl@0
  1694
sl@0
  1695
//
sl@0
  1696
// DoControl - Synchronous requests
sl@0
  1697
//
sl@0
  1698
// Called from HandleMsg.
sl@0
  1699
sl@0
  1700
TInt DLddUsbcScChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
sl@0
  1701
	{
sl@0
  1702
	__KTRACE_OPT(KUSB, Kern::Printf("DoControl: %d", aFunction));
sl@0
  1703
sl@0
  1704
	TInt r = KErrNone;
sl@0
  1705
	TInt ep, param;
sl@0
  1706
	TUsbcScEndpoint* pEndpoint;
sl@0
  1707
	TPtrC8 pZeroDesc(NULL, 0);
sl@0
  1708
	TEndpointDescriptorInfo epInfo;
sl@0
  1709
	TUsbcScIfcInfo ifcInfo;
sl@0
  1710
	TCSDescriptorInfo desInfo;
sl@0
  1711
	TUsbcEndpointResource epRes;
sl@0
  1712
sl@0
  1713
	switch (aFunction)
sl@0
  1714
		{
sl@0
  1715
	case RDevUsbcScClient::EControlEndpointZeroRequestError:
sl@0
  1716
		__KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroRequestError"));
sl@0
  1717
		r = KErrNone;
sl@0
  1718
		if (iOwnsDeviceControl || (iValidInterface && iDeviceState == EUsbcDeviceStateConfigured))
sl@0
  1719
			{
sl@0
  1720
			iController->Ep0Stall(this);
sl@0
  1721
			}
sl@0
  1722
		else
sl@0
  1723
			{
sl@0
  1724
			if (iDeviceState != EUsbcDeviceStateConfigured)
sl@0
  1725
				r = KErrUsbDeviceNotConfigured;
sl@0
  1726
			else
sl@0
  1727
				r = KErrUsbInterfaceNotReady;
sl@0
  1728
			}
sl@0
  1729
		break;
sl@0
  1730
sl@0
  1731
	case RDevUsbcScClient::EControlGetAlternateSetting:
sl@0
  1732
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetAlternateSetting"));
sl@0
  1733
		if (iValidInterface && iDeviceState == EUsbcDeviceStateConfigured)
sl@0
  1734
			{
sl@0
  1735
			r = iController->GetInterfaceNumber(this, param);
sl@0
  1736
			if (r == KErrNone)
sl@0
  1737
				{
sl@0
  1738
				r = Kern::ThreadRawWrite(iClient, a1, &param, sizeof(param), iClient);
sl@0
  1739
				if (r != KErrNone)
sl@0
  1740
					PanicClientThread(r);
sl@0
  1741
				}
sl@0
  1742
			}
sl@0
  1743
		else
sl@0
  1744
			{
sl@0
  1745
			if (iDeviceState != EUsbcDeviceStateConfigured)
sl@0
  1746
				r = KErrUsbDeviceNotConfigured;
sl@0
  1747
			else
sl@0
  1748
				r = KErrUsbInterfaceNotReady;
sl@0
  1749
			}
sl@0
  1750
		break;
sl@0
  1751
sl@0
  1752
	case RDevUsbcScClient::EControlDeviceStatus:
sl@0
  1753
		__KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceStatus"));
sl@0
  1754
		param = iController->GetDeviceStatus();
sl@0
  1755
		r = Kern::ThreadRawWrite(iClient, a1, &param, sizeof(param), iClient);
sl@0
  1756
		if (r != KErrNone)
sl@0
  1757
			PanicClientThread(r);
sl@0
  1758
		break;
sl@0
  1759
sl@0
  1760
	case RDevUsbcScClient::EControlEndpointStatus:
sl@0
  1761
		__KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointStatus"));
sl@0
  1762
		if (iValidInterface && ValidEndpoint((TInt) a1))
sl@0
  1763
			{
sl@0
  1764
			pEndpoint = iEndpoint[(TInt)a1];
sl@0
  1765
			if (pEndpoint == NULL)
sl@0
  1766
				r = KErrNotSupported;
sl@0
  1767
			else
sl@0
  1768
				{
sl@0
  1769
				param = iController->GetEndpointStatus(this, iEndpoint[(TInt)a1]->RealEpNumber());
sl@0
  1770
				r = Kern::ThreadRawWrite(iClient, a2, &param, sizeof(param), iClient);
sl@0
  1771
				if (r != KErrNone)
sl@0
  1772
					PanicClientThread(r);
sl@0
  1773
				}
sl@0
  1774
			}
sl@0
  1775
		else
sl@0
  1776
			{
sl@0
  1777
			if (iDeviceState != EUsbcDeviceStateConfigured)
sl@0
  1778
				r = KErrUsbDeviceNotConfigured;
sl@0
  1779
			else
sl@0
  1780
				r = KErrUsbInterfaceNotReady;
sl@0
  1781
			}
sl@0
  1782
		break;
sl@0
  1783
sl@0
  1784
	case RDevUsbcScClient::EControlEndpointCaps:
sl@0
  1785
		__KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointCaps"));
sl@0
  1786
		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
sl@0
  1787
		if (r != KErrNone)
sl@0
  1788
			PanicClientThread(r);
sl@0
  1789
		iController->EndpointCaps(this, *((TDes8*) a1));
sl@0
  1790
		break;
sl@0
  1791
sl@0
  1792
	case RDevUsbcScClient::EControlDeviceCaps:
sl@0
  1793
		__KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceCaps"));
sl@0
  1794
		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
sl@0
  1795
		if (r != KErrNone)
sl@0
  1796
			PanicClientThread(r);
sl@0
  1797
		iController->DeviceCaps(this, *((TDes8*) a1));
sl@0
  1798
		break;
sl@0
  1799
sl@0
  1800
	case RDevUsbcScClient::EControlSendEp0StatusPacket:
sl@0
  1801
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSendEp0StatusPacket"));
sl@0
  1802
		iController->SendEp0StatusPacket(this);
sl@0
  1803
		break;
sl@0
  1804
sl@0
  1805
	case RDevUsbcScClient::EControlHaltEndpoint:
sl@0
  1806
		__KTRACE_OPT(KUSB, Kern::Printf("EControlHaltEndpoint"));
sl@0
  1807
		if (iValidInterface && ValidEndpoint((TInt) a1))
sl@0
  1808
			{
sl@0
  1809
			r = iController->HaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
sl@0
  1810
			}
sl@0
  1811
		else
sl@0
  1812
			{
sl@0
  1813
			if (iDeviceState != EUsbcDeviceStateConfigured)
sl@0
  1814
				r = KErrUsbDeviceNotConfigured;
sl@0
  1815
			else
sl@0
  1816
				r = KErrUsbInterfaceNotReady;
sl@0
  1817
			}
sl@0
  1818
		break;
sl@0
  1819
sl@0
  1820
	case RDevUsbcScClient::EControlClearHaltEndpoint:
sl@0
  1821
		__KTRACE_OPT(KUSB, Kern::Printf("EControlClearHaltEndpoint"));
sl@0
  1822
		if (iValidInterface && ValidEndpoint((TInt) a1))
sl@0
  1823
			{
sl@0
  1824
			r = iController->ClearHaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
sl@0
  1825
			}
sl@0
  1826
		else
sl@0
  1827
			{
sl@0
  1828
			if (iDeviceState != EUsbcDeviceStateConfigured)
sl@0
  1829
				r = KErrUsbDeviceNotConfigured;
sl@0
  1830
			else
sl@0
  1831
				r = KErrUsbInterfaceNotReady;
sl@0
  1832
			}
sl@0
  1833
		break;
sl@0
  1834
sl@0
  1835
	case RDevUsbcScClient::EControlDumpRegisters:
sl@0
  1836
		__KTRACE_OPT(KUSB, Kern::Printf("EControlDumpRegisters"));
sl@0
  1837
		iController->DumpRegisters();
sl@0
  1838
		break;
sl@0
  1839
sl@0
  1840
	case RDevUsbcScClient::EControlReleaseDeviceControl:
sl@0
  1841
		__KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseDeviceControl"));
sl@0
  1842
		iController->ReleaseDeviceControl(this);
sl@0
  1843
		iOwnsDeviceControl = EFalse;
sl@0
  1844
		break;
sl@0
  1845
sl@0
  1846
	case RDevUsbcScClient::EControlEndpointZeroMaxPacketSizes:
sl@0
  1847
		__KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroMaxPacketSizes"));
sl@0
  1848
		r = iController->EndpointZeroMaxPacketSizes();
sl@0
  1849
		break;
sl@0
  1850
sl@0
  1851
	case RDevUsbcScClient::EControlSetEndpointZeroMaxPacketSize:
sl@0
  1852
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointZeroMaxPacketSize"));
sl@0
  1853
		r = iController->SetEndpointZeroMaxPacketSize(reinterpret_cast<TInt>(a1));
sl@0
  1854
		break;
sl@0
  1855
sl@0
  1856
	case RDevUsbcScClient::EControlGetEndpointZeroMaxPacketSize:
sl@0
  1857
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointZeroMaxPacketSize"));
sl@0
  1858
		r = iController->Ep0PacketSize();
sl@0
  1859
		break;
sl@0
  1860
sl@0
  1861
	case RDevUsbcScClient::EControlGetDeviceDescriptor:
sl@0
  1862
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptor"));
sl@0
  1863
		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
sl@0
  1864
		if (r != KErrNone)
sl@0
  1865
			PanicClientThread(r);
sl@0
  1866
		r = iController->GetDeviceDescriptor(iClient, *((TDes8*) a1));
sl@0
  1867
		break;
sl@0
  1868
sl@0
  1869
	case RDevUsbcScClient::EControlSetDeviceDescriptor:
sl@0
  1870
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceDescriptor"));
sl@0
  1871
		BREAK_IF_NULL_ARG(a1,r);
sl@0
  1872
		r = iController->SetDeviceDescriptor(iClient, *((TDes8*) a1));
sl@0
  1873
		break;
sl@0
  1874
sl@0
  1875
	case RDevUsbcScClient::EControlGetDeviceDescriptorSize:
sl@0
  1876
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptorSize"));
sl@0
  1877
		BREAK_IF_NULL_ARG(a1,r);
sl@0
  1878
		r = iController->GetDeviceDescriptorSize(iClient, *((TDes8*) a1));
sl@0
  1879
		break;
sl@0
  1880
sl@0
  1881
	case RDevUsbcScClient::EControlGetConfigurationDescriptor:
sl@0
  1882
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptor"));
sl@0
  1883
		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
sl@0
  1884
		if (r != KErrNone)
sl@0
  1885
			PanicClientThread(r);
sl@0
  1886
		r = iController->GetConfigurationDescriptor(iClient, *((TDes8*) a1));
sl@0
  1887
		break;
sl@0
  1888
sl@0
  1889
	case RDevUsbcScClient::EControlGetConfigurationDescriptorSize:
sl@0
  1890
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptorSize"));
sl@0
  1891
		if (a1 != NULL)
sl@0
  1892
			{
sl@0
  1893
			r = iController->GetConfigurationDescriptorSize(iClient, *((TDes8*) a1));
sl@0
  1894
			}
sl@0
  1895
		else
sl@0
  1896
			r = KErrArgument;
sl@0
  1897
		break;
sl@0
  1898
sl@0
  1899
	case RDevUsbcScClient::EControlSetConfigurationDescriptor:
sl@0
  1900
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationDescriptor"));
sl@0
  1901
		r = iController->SetConfigurationDescriptor(iClient, *((TDes8*) a1));
sl@0
  1902
		break;
sl@0
  1903
sl@0
  1904
	case RDevUsbcScClient::EControlGetInterfaceDescriptor:
sl@0
  1905
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptor"));
sl@0
  1906
		r = iController->GetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
sl@0
  1907
		break;
sl@0
  1908
sl@0
  1909
	case RDevUsbcScClient::EControlGetInterfaceDescriptorSize:
sl@0
  1910
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptorSize"));
sl@0
  1911
		r = iController->GetInterfaceDescriptorSize(iClient, this, (TInt) a1, *(TDes8*) a2);
sl@0
  1912
		break;
sl@0
  1913
sl@0
  1914
	case RDevUsbcScClient::EControlSetInterfaceDescriptor:
sl@0
  1915
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterfaceDescriptor"));
sl@0
  1916
		r = iController->SetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
sl@0
  1917
		break;
sl@0
  1918
sl@0
  1919
	case RDevUsbcScClient::EControlGetEndpointDescriptor:
sl@0
  1920
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptor"));
sl@0
  1921
		r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
sl@0
  1922
		if (r != KErrNone)
sl@0
  1923
			PanicClientThread(r);
sl@0
  1924
		ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
sl@0
  1925
		r = (ep<0)?ep:iController->GetEndpointDescriptor(iClient, this, epInfo.iSetting,
sl@0
  1926
											   ep, *(TDes8*) epInfo.iArg);
sl@0
  1927
		break;
sl@0
  1928
sl@0
  1929
	case RDevUsbcScClient::EControlGetEndpointDescriptorSize:
sl@0
  1930
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptorSize"));
sl@0
  1931
		r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
sl@0
  1932
		if (r != KErrNone)
sl@0
  1933
			PanicClientThread(r);
sl@0
  1934
		ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
sl@0
  1935
		r = iController->GetEndpointDescriptorSize(iClient, this, epInfo.iSetting,
sl@0
  1936
												   ep, *(TDes8*) epInfo.iArg);
sl@0
  1937
		break;
sl@0
  1938
sl@0
  1939
	case RDevUsbcScClient::EControlSetEndpointDescriptor:
sl@0
  1940
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointDescriptor"));
sl@0
  1941
		r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
sl@0
  1942
		if (r != KErrNone)
sl@0
  1943
			PanicClientThread(r);
sl@0
  1944
		ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
sl@0
  1945
		r = iController->SetEndpointDescriptor(iClient, this, epInfo.iSetting,
sl@0
  1946
											   ep, *(TDes8*)epInfo.iArg);
sl@0
  1947
		break;
sl@0
  1948
sl@0
  1949
	case RDevUsbcScClient::EControlGetDeviceQualifierDescriptor:
sl@0
  1950
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceQualifierDescriptor"));
sl@0
  1951
		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
sl@0
  1952
		if (r != KErrNone)
sl@0
  1953
			PanicClientThread(r);
sl@0
  1954
		r = iController->GetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
sl@0
  1955
		break;
sl@0
  1956
sl@0
  1957
	case RDevUsbcScClient::EControlSetDeviceQualifierDescriptor:
sl@0
  1958
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceQualifierDescriptor"));
sl@0
  1959
		BREAK_IF_NULL_ARG(a1,r);
sl@0
  1960
		r = iController->SetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
sl@0
  1961
		break;
sl@0
  1962
sl@0
  1963
	case RDevUsbcScClient::EControlGetOtherSpeedConfigurationDescriptor:
sl@0
  1964
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtherSpeedConfigurationDescriptor"));
sl@0
  1965
		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
sl@0
  1966
		if (r != KErrNone)
sl@0
  1967
			PanicClientThread(r);
sl@0
  1968
		r = iController->GetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
sl@0
  1969
		break;
sl@0
  1970
sl@0
  1971
	case RDevUsbcScClient::EControlSetOtherSpeedConfigurationDescriptor:
sl@0
  1972
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtherSpeedConfigurationDescriptor"));
sl@0
  1973
		r = iController->SetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
sl@0
  1974
		break;
sl@0
  1975
sl@0
  1976
sl@0
  1977
	case RDevUsbcScClient::EControlGetCSInterfaceDescriptor:
sl@0
  1978
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptor"));
sl@0
  1979
		r = iController->GetCSInterfaceDescriptorBlock(iClient, this, (TInt) a1, *((TDes8*) a2));
sl@0
  1980
		break;
sl@0
  1981
sl@0
  1982
	case RDevUsbcScClient::EControlGetCSInterfaceDescriptorSize:
sl@0
  1983
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptorSize"));
sl@0
  1984
		r = iController->GetCSInterfaceDescriptorBlockSize(iClient, this, (TInt) a1, *(TDes8*) a2);
sl@0
  1985
		break;
sl@0
  1986
sl@0
  1987
	case RDevUsbcScClient::EControlGetCSEndpointDescriptor:
sl@0
  1988
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptor"));
sl@0
  1989
		r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
sl@0
  1990
		if (r != KErrNone)
sl@0
  1991
			PanicClientThread(r);
sl@0
  1992
		ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
sl@0
  1993
		r = iController->GetCSEndpointDescriptorBlock(iClient, this, epInfo.iSetting,
sl@0
  1994
													  ep, *(TDes8*) epInfo.iArg);
sl@0
  1995
		break;
sl@0
  1996
sl@0
  1997
	case RDevUsbcScClient::EControlGetCSEndpointDescriptorSize:
sl@0
  1998
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptorSize"));
sl@0
  1999
		r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
sl@0
  2000
		if (r != KErrNone)
sl@0
  2001
			PanicClientThread(r);
sl@0
  2002
		ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
sl@0
  2003
		r = iController->GetCSEndpointDescriptorBlockSize(iClient, this, epInfo.iSetting,
sl@0
  2004
														  ep, *(TDes8*) epInfo.iArg);
sl@0
  2005
		break;
sl@0
  2006
sl@0
  2007
	case RDevUsbcScClient::EControlSignalRemoteWakeup:
sl@0
  2008
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSignalRemoteWakeup"));
sl@0
  2009
		r = iController->SignalRemoteWakeup();
sl@0
  2010
		break;
sl@0
  2011
sl@0
  2012
	case RDevUsbcScClient::EControlDeviceDisconnectFromHost:
sl@0
  2013
		__KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceDisconnectFromHost"));
sl@0
  2014
		r = iController->UsbDisconnect();
sl@0
  2015
		break;
sl@0
  2016
sl@0
  2017
	case RDevUsbcScClient::EControlDeviceConnectToHost:
sl@0
  2018
		__KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceConnectToHost"));
sl@0
  2019
		r = iController->UsbConnect();
sl@0
  2020
		break;
sl@0
  2021
sl@0
  2022
	case RDevUsbcScClient::EControlDevicePowerUpUdc:
sl@0
  2023
		__KTRACE_OPT(KUSB, Kern::Printf("EControlDevicePowerUpUdc"));
sl@0
  2024
		r = iController->PowerUpUdc();
sl@0
  2025
		break;
sl@0
  2026
sl@0
  2027
	case RDevUsbcScClient::EControlSetDeviceControl:
sl@0
  2028
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
sl@0
  2029
		r = iController->SetDeviceControl(this);
sl@0
  2030
		if (r == KErrNone)
sl@0
  2031
			{
sl@0
  2032
			iOwnsDeviceControl = ETrue;
sl@0
  2033
			if (iEp0Endpoint == NULL)
sl@0
  2034
				{
sl@0
  2035
				__KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
sl@0
  2036
				r = SetupEp0();
sl@0
  2037
				if (r != KErrNone)
sl@0
  2038
					{
sl@0
  2039
					__KTRACE_OPT(KPANIC, Kern::Printf("  Error: SetupEp0() failed"));
sl@0
  2040
					iController->ReleaseDeviceControl(this);
sl@0
  2041
					iOwnsDeviceControl=EFalse;
sl@0
  2042
					DestroyEp0();
sl@0
  2043
					}
sl@0
  2044
				}
sl@0
  2045
			}
sl@0
  2046
		else
sl@0
  2047
			r = KErrInUse;
sl@0
  2048
		break;
sl@0
  2049
sl@0
  2050
	case RDevUsbcScClient::EControlCurrentlyUsingHighSpeed:
sl@0
  2051
		__KTRACE_OPT(KUSB, Kern::Printf("EControlCurrentlyUsingHighSpeed"));
sl@0
  2052
		r = iController->CurrentlyUsingHighSpeed();
sl@0
  2053
		break;
sl@0
  2054
sl@0
  2055
	case RDevUsbcScClient::EControlSetInterface:
sl@0
  2056
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterface"));
sl@0
  2057
		r = Kern::ThreadRawRead(iClient, a2, &ifcInfo, sizeof(ifcInfo));
sl@0
  2058
		if (r != KErrNone)
sl@0
  2059
			PanicClientThread(r);
sl@0
  2060
		r = SetInterface((TInt) a1, &ifcInfo);
sl@0
  2061
		break;
sl@0
  2062
sl@0
  2063
	case RDevUsbcScClient::EControlReleaseInterface: 
sl@0
  2064
		__KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseInterface"));
sl@0
  2065
		if (!iRealizeCalled)
sl@0
  2066
			{
sl@0
  2067
			r = iController->ReleaseInterface(this, (TInt) a1);
sl@0
  2068
			if (r == KErrNone)
sl@0
  2069
				{
sl@0
  2070
				DestroyInterface((TUint) a1);
sl@0
  2071
				}
sl@0
  2072
			else
sl@0
  2073
				{
sl@0
  2074
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error in PIL: LDD interface won't be released."));
sl@0
  2075
				}
sl@0
  2076
			}
sl@0
  2077
		else
sl@0
  2078
			r = KErrUsbAlreadyRealized;
sl@0
  2079
		break;
sl@0
  2080
sl@0
  2081
	case RDevUsbcScClient::EControlSetCSInterfaceDescriptor:
sl@0
  2082
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSInterfaceDescriptor"));
sl@0
  2083
		r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
sl@0
  2084
		if (r != KErrNone)
sl@0
  2085
			PanicClientThread(r);
sl@0
  2086
		r = iController->SetCSInterfaceDescriptorBlock(iClient, this, desInfo.iSetting,
sl@0
  2087
													   *reinterpret_cast<const TDes8*>(desInfo.iArg),
sl@0
  2088
													   desInfo.iSize);
sl@0
  2089
		break;
sl@0
  2090
sl@0
  2091
	case RDevUsbcScClient::EControlSetCSEndpointDescriptor:
sl@0
  2092
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSEndpointDescriptor"));
sl@0
  2093
		r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
sl@0
  2094
		if (r != KErrNone)
sl@0
  2095
			PanicClientThread(r);
sl@0
  2096
		ep = EpFromAlternateSetting(desInfo.iSetting, desInfo.iEndpoint);
sl@0
  2097
		r = iController->SetCSEndpointDescriptorBlock(iClient, this, desInfo.iSetting, ep,
sl@0
  2098
													  *reinterpret_cast<const TDes8*>(desInfo.iArg),
sl@0
  2099
													  desInfo.iSize);
sl@0
  2100
		break;
sl@0
  2101
sl@0
  2102
	case RDevUsbcScClient::EControlGetStringDescriptorLangId:
sl@0
  2103
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptorLangId"));
sl@0
  2104
		r = iController->GetStringDescriptorLangId(iClient, *((TDes8*) a1));
sl@0
  2105
		break;
sl@0
  2106
sl@0
  2107
	case RDevUsbcScClient::EControlSetStringDescriptorLangId:
sl@0
  2108
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptorLangId"));
sl@0
  2109
		r = iController->SetStringDescriptorLangId(reinterpret_cast<TUint>(a1));
sl@0
  2110
		break;
sl@0
  2111
sl@0
  2112
	case RDevUsbcScClient::EControlGetManufacturerStringDescriptor:
sl@0
  2113
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetManufacturerStringDescriptor"));
sl@0
  2114
		r = iController->GetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
sl@0
  2115
		break;
sl@0
  2116
sl@0
  2117
	case RDevUsbcScClient::EControlSetManufacturerStringDescriptor:
sl@0
  2118
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetManufacturerStringDescriptor"));
sl@0
  2119
		r = iController->SetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
sl@0
  2120
		break;
sl@0
  2121
sl@0
  2122
	case RDevUsbcScClient::EControlRemoveManufacturerStringDescriptor:
sl@0
  2123
		__KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveManufacturerStringDescriptor"));
sl@0
  2124
		r = iController->RemoveManufacturerStringDescriptor();
sl@0
  2125
		break;
sl@0
  2126
sl@0
  2127
	case RDevUsbcScClient::EControlGetProductStringDescriptor:
sl@0
  2128
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetProductStringDescriptor"));
sl@0
  2129
		r = iController->GetProductStringDescriptor(iClient, *((TPtr8*) a1));
sl@0
  2130
		break;
sl@0
  2131
sl@0
  2132
	case RDevUsbcScClient::EControlSetProductStringDescriptor:
sl@0
  2133
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetProductStringDescriptor"));
sl@0
  2134
		r = iController->SetProductStringDescriptor(iClient, *((TPtr8*) a1));
sl@0
  2135
		break;
sl@0
  2136
sl@0
  2137
	case RDevUsbcScClient::EControlRemoveProductStringDescriptor:
sl@0
  2138
		__KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveProductStringDescriptor"));
sl@0
  2139
		r = iController->RemoveProductStringDescriptor();
sl@0
  2140
		break;
sl@0
  2141
sl@0
  2142
	case RDevUsbcScClient::EControlGetSerialNumberStringDescriptor:
sl@0
  2143
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetSerialNumberStringDescriptor"));
sl@0
  2144
		r = iController->GetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
sl@0
  2145
		break;
sl@0
  2146
sl@0
  2147
	case RDevUsbcScClient::EControlSetSerialNumberStringDescriptor:
sl@0
  2148
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetSerialNumberStringDescriptor"));
sl@0
  2149
		r = iController->SetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
sl@0
  2150
		break;
sl@0
  2151
sl@0
  2152
	case RDevUsbcScClient::EControlRemoveSerialNumberStringDescriptor:
sl@0
  2153
		__KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveSerialNumberStringDescriptor"));
sl@0
  2154
		r = iController->RemoveSerialNumberStringDescriptor();
sl@0
  2155
		break;
sl@0
  2156
sl@0
  2157
	case RDevUsbcScClient::EControlGetConfigurationStringDescriptor:
sl@0
  2158
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationStringDescriptor"));
sl@0
  2159
		r = iController->GetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
sl@0
  2160
		break;
sl@0
  2161
sl@0
  2162
	case RDevUsbcScClient::EControlSetConfigurationStringDescriptor:
sl@0
  2163
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationStringDescriptor"));
sl@0
  2164
		r = iController->SetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
sl@0
  2165
		break;
sl@0
  2166
sl@0
  2167
	case RDevUsbcScClient::EControlRemoveConfigurationStringDescriptor:
sl@0
  2168
		__KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveConfigurationStringDescriptor"));
sl@0
  2169
		r = iController->RemoveConfigurationStringDescriptor();
sl@0
  2170
		break;
sl@0
  2171
sl@0
  2172
	case RDevUsbcScClient::EControlGetStringDescriptor:
sl@0
  2173
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptor"));
sl@0
  2174
		r = iController->GetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
sl@0
  2175
		break;
sl@0
  2176
sl@0
  2177
	case RDevUsbcScClient::EControlSetStringDescriptor:
sl@0
  2178
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptor"));
sl@0
  2179
		r = iController->SetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
sl@0
  2180
		break;
sl@0
  2181
sl@0
  2182
	case RDevUsbcScClient::EControlRemoveStringDescriptor:
sl@0
  2183
		__KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveStringDescriptor"));
sl@0
  2184
		r = iController->RemoveStringDescriptor((TUint8) (TInt) a1);
sl@0
  2185
		break;
sl@0
  2186
sl@0
  2187
	case RDevUsbcScClient::EControlAllocateEndpointResource:
sl@0
  2188
		{
sl@0
  2189
		__KTRACE_OPT(KUSB, Kern::Printf("EControlAllocateEndpointResource"));
sl@0
  2190
		epRes = (TUsbcEndpointResource)((TInt) a2);
sl@0
  2191
		TInt realEp=-1;
sl@0
  2192
		r = GetRealEpForEpResource((TInt)a1, realEp);
sl@0
  2193
		if (r==KErrNone)
sl@0
  2194
			r = iController->AllocateEndpointResource(this, realEp, epRes);
sl@0
  2195
		break;
sl@0
  2196
		}
sl@0
  2197
	case RDevUsbcScClient::EControlDeAllocateEndpointResource:
sl@0
  2198
		{
sl@0
  2199
		__KTRACE_OPT(KUSB, Kern::Printf("EControlDeAllocateEndpointResource"));
sl@0
  2200
		epRes = (TUsbcEndpointResource)((TInt) a2);
sl@0
  2201
		TInt realEp=-1;
sl@0
  2202
		r = GetRealEpForEpResource((TInt)a1, realEp);
sl@0
  2203
		if (r==KErrNone)
sl@0
  2204
			r = iController->DeAllocateEndpointResource(this, realEp, epRes);
sl@0
  2205
		break;
sl@0
  2206
		}
sl@0
  2207
	case RDevUsbcScClient::EControlQueryEndpointResourceUse:
sl@0
  2208
		{
sl@0
  2209
		__KTRACE_OPT(KUSB, Kern::Printf("EControlQueryEndpointResourceUse"));
sl@0
  2210
		epRes = (TUsbcEndpointResource)((TInt) a2);
sl@0
  2211
		TInt realEp=-1;
sl@0
  2212
		r = GetRealEpForEpResource((TInt)a1, realEp);
sl@0
  2213
		if (r==KErrNone)
sl@0
  2214
			r = iController->QueryEndpointResource(this, realEp, epRes);
sl@0
  2215
		break;
sl@0
  2216
		}
sl@0
  2217
	case RDevUsbcScClient::EControlSetOtgDescriptor:
sl@0
  2218
		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtgDescriptor"));
sl@0
  2219
		r = iController->SetOtgDescriptor(iClient, *((const TDesC8*)a1));
sl@0
  2220
		break;
sl@0
  2221
sl@0
  2222
	case RDevUsbcScClient::EControlGetOtgDescriptor:
sl@0
  2223
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtgDescriptor"));
sl@0
  2224
		r = iController->GetOtgDescriptor(iClient, *((TDes8*)a1));
sl@0
  2225
		break;
sl@0
  2226
sl@0
  2227
	case RDevUsbcScClient::EControlGetOtgFeatures:
sl@0
  2228
		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtgFeatures"));
sl@0
  2229
		r = iController->GetOtgFeatures(iClient, *((TDes8*)a1));
sl@0
  2230
		break;
sl@0
  2231
sl@0
  2232
	case RDevUsbcScClient::EControlRealizeInterface:
sl@0
  2233
		__KTRACE_OPT(KUSB, Kern::Printf("EControlRealizeInterface"));
sl@0
  2234
		r = RealizeInterface();
sl@0
  2235
		break;
sl@0
  2236
	case RDevUsbcScClient::EControlStartNextInAlternateSetting:
sl@0
  2237
		__KTRACE_OPT(KUSB, Kern::Printf("EControlStartNextInAlternateSetting"));
sl@0
  2238
		r = StartNextInAlternateSetting();
sl@0
  2239
		break;
sl@0
  2240
sl@0
  2241
    default:
sl@0
  2242
		__KTRACE_OPT(KUSB, Kern::Printf("Function code not supported"));
sl@0
  2243
		r = KErrNotSupported;
sl@0
  2244
		}
sl@0
  2245
sl@0
  2246
	return r;
sl@0
  2247
	}
sl@0
  2248
// end DoControl.
sl@0
  2249
sl@0
  2250
sl@0
  2251
sl@0
  2252
//
sl@0
  2253
// Overriding DObject virtual
sl@0
  2254
//
sl@0
  2255
TInt DLddUsbcScChannel::RequestUserHandle(DThread* aThread, TOwnerType /*aType*/)
sl@0
  2256
	{
sl@0
  2257
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::RequestUserHandle"));
sl@0
  2258
	// The USB client LDD is not designed for a channel to be shared between
sl@0
  2259
	// threads. It saves a pointer to the current thread when it is opened, and
sl@0
  2260
	// uses this to complete any asynchronous requests.
sl@0
  2261
	// It is therefore not acceptable for the handle to be duplicated and used
sl@0
  2262
	// by another thread:
sl@0
  2263
	if (aThread == iClient)
sl@0
  2264
		{
sl@0
  2265
		return KErrNone;
sl@0
  2266
		}
sl@0
  2267
	else
sl@0
  2268
		{
sl@0
  2269
		return KErrAccessDenied;
sl@0
  2270
		}
sl@0
  2271
	}
sl@0
  2272
sl@0
  2273
inline TInt DLddUsbcScChannel::GetRealEpForEpResource(TInt aEndpoint, TInt& aRealEp)
sl@0
  2274
	{
sl@0
  2275
	if (iEndpoint) // if we've enumerated at least once, proceed as normal.
sl@0
  2276
		{
sl@0
  2277
		if  (aEndpoint <= iNumberOfEndpoints && aEndpoint >= 0)
sl@0
  2278
			{
sl@0
  2279
			aRealEp=iEndpoint[aEndpoint]->RealEpNumber();
sl@0
  2280
			return KErrNone;
sl@0
  2281
			}
sl@0
  2282
		}
sl@0
  2283
	else // Assume alternate setting 0.
sl@0
  2284
		{
sl@0
  2285
		if (iAlternateSettingList)   // Check it has been set up.
sl@0
  2286
			{
sl@0
  2287
			TUsbcScAlternateSetting* alt = iAlternateSettingList->iHead;
sl@0
  2288
			if (alt &&  (aEndpoint <= alt->iNumberOfEndpoints && aEndpoint >= 0))
sl@0
  2289
				{
sl@0
  2290
				aRealEp= alt->iEndpoint[aEndpoint]->RealEpNumber();
sl@0
  2291
				return KErrNone;
sl@0
  2292
				}
sl@0
  2293
			}
sl@0
  2294
		}
sl@0
  2295
	return KErrUsbDeviceNotConfigured;
sl@0
  2296
	}
sl@0
  2297
sl@0
  2298
sl@0
  2299
TUsbcEndpointInfoArray::TUsbcEndpointInfoArray(const TUsbcScEndpointInfo* aData, TInt aDataSize)
sl@0
  2300
	{
sl@0
  2301
	iType = EUsbcScEndpointInfo;
sl@0
  2302
	iData = (TUint8*) aData;	
sl@0
  2303
	if (aDataSize>0)
sl@0
  2304
		iDataSize = aDataSize;
sl@0
  2305
	else
sl@0
  2306
		iDataSize = sizeof(TUsbcScEndpointInfo);
sl@0
  2307
	}
sl@0
  2308
sl@0
  2309
sl@0
  2310
//
sl@0
  2311
// SetInterface
sl@0
  2312
//
sl@0
  2313
// Called from DoControl.  Sets the configuration of a given Interface.					// Needs changing
sl@0
  2314
// All interfaces must be configured before one can be used.  
sl@0
  2315
//
sl@0
  2316
sl@0
  2317
TInt DLddUsbcScChannel::SetInterface(TInt aInterfaceNumber, TUsbcScIfcInfo* aInfoBuf)
sl@0
  2318
	{
sl@0
  2319
	// Copy interface description.
sl@0
  2320
sl@0
  2321
	if (iRealizeCalled)
sl@0
  2322
		return KErrUsbAlreadyRealized;
sl@0
  2323
sl@0
  2324
	if (!iAlternateSettingList)
sl@0
  2325
		{
sl@0
  2326
		iAlternateSettingList = new TUsbcScAlternateSettingList;
sl@0
  2327
		if (iAlternateSettingList==NULL)
sl@0
  2328
			{
sl@0
  2329
			return KErrNoMemory;
sl@0
  2330
			}
sl@0
  2331
		}
sl@0
  2332
sl@0
  2333
	// Read descriptor in
sl@0
  2334
	TUsbcScInterfaceInfoBuf ifc_info_buf;
sl@0
  2335
	TUsbcScInterfaceInfoBuf* const ifc_info_buf_ptr = aInfoBuf->iInterfaceData;
sl@0
  2336
	const TInt srcLen = Kern::ThreadGetDesLength(iClient, ifc_info_buf_ptr);
sl@0
  2337
sl@0
  2338
	__KTRACE_OPT(KUSB, Kern::Printf("SetInterface srcLen = %d len = %d", srcLen, ifc_info_buf.Length() ));
sl@0
  2339
sl@0
  2340
	if (srcLen < ifc_info_buf.Length())
sl@0
  2341
		{
sl@0
  2342
		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface can't copy"));
sl@0
  2343
		PanicClientThread(EDesOverflow);
sl@0
  2344
		}
sl@0
  2345
sl@0
  2346
	TInt r = Kern::ThreadDesRead(iClient, ifc_info_buf_ptr, ifc_info_buf, 0, KChunkShiftBy0);
sl@0
  2347
	if (r != KErrNone)
sl@0
  2348
		{
sl@0
  2349
		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface Copy failed reason=%d", r));
sl@0
  2350
		PanicClientThread(r);
sl@0
  2351
		}
sl@0
  2352
sl@0
  2353
	// The list of endpoints is within the interface info.
sl@0
  2354
	TUsbcScEndpointInfo* pEndpointData = ifc_info_buf().iEndpointData;
sl@0
  2355
sl@0
  2356
	const TInt num_endpoints = ifc_info_buf().iTotalEndpointsUsed;
sl@0
  2357
	__KTRACE_OPT(KUSB, Kern::Printf("SetInterface num_endpoints=%d", num_endpoints));
sl@0
  2358
	if (num_endpoints>KMaxEndpointsPerClient)
sl@0
  2359
		return KErrOverflow;
sl@0
  2360
sl@0
  2361
sl@0
  2362
	// Initialize real ep numbers list.
sl@0
  2363
	TInt i;
sl@0
  2364
	TInt real_ep_numbers[KMaxEndpointsPerClient+1]; // range 1->KMaxEndpointsPerClient (0 not used)
sl@0
  2365
	for (i=0; i<=KMaxEndpointsPerClient; i++)
sl@0
  2366
		real_ep_numbers[i] = -1;
sl@0
  2367
sl@0
  2368
sl@0
  2369
	// See if PIL will accept this interface
sl@0
  2370
	__KTRACE_OPT(KUSB, Kern::Printf("SetInterface Calling controller"));
sl@0
  2371
	TUsbcEndpointInfoArray endpointData = TUsbcEndpointInfoArray(ifc_info_buf().iEndpointData);
sl@0
  2372
sl@0
  2373
	r = iController->SetInterface(this,
sl@0
  2374
								  iClient,
sl@0
  2375
								  aInterfaceNumber,
sl@0
  2376
								  ifc_info_buf().iClass,
sl@0
  2377
								  aInfoBuf->iString,
sl@0
  2378
								  (TInt) ifc_info_buf().iTotalEndpointsUsed,
sl@0
  2379
								  endpointData,
sl@0
  2380
								  &real_ep_numbers[0],
sl@0
  2381
								  ifc_info_buf().iFeatureWord);
sl@0
  2382
sl@0
  2383
	__KTRACE_OPT(KUSB, Kern::Printf("SetInterface controller returned %d", r));
sl@0
  2384
	if (r != KErrNone)
sl@0
  2385
		{
sl@0
  2386
		__KTRACE_OPT(KPANIC, Kern::Printf("SetInterface failed reason=%d", r));
sl@0
  2387
		return r;
sl@0
  2388
		}
sl@0
  2389
sl@0
  2390
	// create alternate setting record
sl@0
  2391
    TUsbcScAlternateSetting* alternateSettingListRec = new TUsbcScAlternateSetting;
sl@0
  2392
	if (!alternateSettingListRec)
sl@0
  2393
		{
sl@0
  2394
		r = KErrNoMemory;
sl@0
  2395
		goto ReleaseInterface;
sl@0
  2396
		}
sl@0
  2397
	
sl@0
  2398
	// other endpoints
sl@0
  2399
	for (TInt i = 1; i <= num_endpoints; i++, pEndpointData++)
sl@0
  2400
		{
sl@0
  2401
		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d", i));
sl@0
  2402
sl@0
  2403
		if ((pEndpointData->iType==KUsbEpTypeControl)
sl@0
  2404
			|| (pEndpointData->iDir != KUsbEpDirIn && pEndpointData->iDir != KUsbEpDirOut)
sl@0
  2405
			|| (pEndpointData->iSize > 1024) || (pEndpointData->iSize<=0))
sl@0
  2406
			{
sl@0
  2407
			r = KErrUsbBadEndpoint;
sl@0
  2408
			goto CleanUp;
sl@0
  2409
			}
sl@0
  2410
		// Check data
sl@0
  2411
sl@0
  2412
		TUint* bufferSize = &(pEndpointData->iBufferSize);
sl@0
  2413
		if (*bufferSize==0)
sl@0
  2414
			*bufferSize= KUsbcScDefaultBufferSize;
sl@0
  2415
sl@0
  2416
		TInt pageSize = Kern::RoundToPageSize(1);
sl@0
  2417
		// Round buffersize up to nearest pagesize.
sl@0
  2418
		*bufferSize = (*bufferSize+pageSize-1) & ~(pageSize-1);
sl@0
  2419
sl@0
  2420
		TUsbcScEndpoint* ep = new TUsbcScEndpoint(this, iController, pEndpointData, i);
sl@0
  2421
		alternateSettingListRec->iEndpoint[i] = ep;
sl@0
  2422
		if (!ep)
sl@0
  2423
			{
sl@0
  2424
			r = KErrNoMemory;
sl@0
  2425
			goto CleanUp;
sl@0
  2426
			}
sl@0
  2427
		if (ep->Construct() != KErrNone)
sl@0
  2428
			{
sl@0
  2429
			r = KErrNoMemory;
sl@0
  2430
			goto CleanUp;
sl@0
  2431
			}
sl@0
  2432
sl@0
  2433
	
sl@0
  2434
		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d rec=0x%08x ep==0x%08x",
sl@0
  2435
										i, alternateSettingListRec, ep));
sl@0
  2436
		}
sl@0
  2437
sl@0
  2438
	if (iAlternateSettingList->iHead)
sl@0
  2439
		{
sl@0
  2440
		iAlternateSettingList->iTail->iNext = alternateSettingListRec;
sl@0
  2441
		alternateSettingListRec->iPrevious = iAlternateSettingList->iTail;
sl@0
  2442
		iAlternateSettingList->iTail = alternateSettingListRec;	
sl@0
  2443
		}
sl@0
  2444
	else
sl@0
  2445
		{
sl@0
  2446
		iAlternateSettingList->iHead = alternateSettingListRec;	
sl@0
  2447
		iAlternateSettingList->iTail = alternateSettingListRec;	
sl@0
  2448
		}	
sl@0
  2449
	
sl@0
  2450
	alternateSettingListRec->iNext = NULL;
sl@0
  2451
	alternateSettingListRec->iSetting = aInterfaceNumber;
sl@0
  2452
	alternateSettingListRec->iNumberOfEndpoints = num_endpoints;
sl@0
  2453
sl@0
  2454
	// Record the 'real' endpoint number used by the PDD in both the Ep and
sl@0
  2455
	// the Req callback:
sl@0
  2456
	for (TInt i = 1; i <= num_endpoints; i++)
sl@0
  2457
		{
sl@0
  2458
		alternateSettingListRec->iEndpoint[i]->SetRealEpNumber(real_ep_numbers[i]);
sl@0
  2459
		}
sl@0
  2460
sl@0
  2461
	return KErrNone;
sl@0
  2462
sl@0
  2463
 CleanUp:
sl@0
  2464
	delete alternateSettingListRec;
sl@0
  2465
	//Fall Through
sl@0
  2466
sl@0
  2467
 ReleaseInterface:
sl@0
  2468
#if _DEBUG
sl@0
  2469
	TInt r1 = iController->ReleaseInterface(this, aInterfaceNumber);
sl@0
  2470
	__KTRACE_OPT(KUSB, Kern::Printf("Release Interface controller returned %d", r1));
sl@0
  2471
#else
sl@0
  2472
	(void)	iController->ReleaseInterface(this, aInterfaceNumber);
sl@0
  2473
#endif
sl@0
  2474
	return r;
sl@0
  2475
	}
sl@0
  2476
// end SetInterface
sl@0
  2477
sl@0
  2478
sl@0
  2479
sl@0
  2480
#ifdef _DEBUG
sl@0
  2481
void RealizeInterface_Dump(TUint* aMem)
sl@0
  2482
	{
sl@0
  2483
	TUint *mem= NULL;
sl@0
  2484
	__KTRACE_OPT(KUSB, mem = aMem);
sl@0
  2485
	if (mem!=NULL)
sl@0
  2486
		{
sl@0
  2487
		TInt j;
sl@0
  2488
 		Kern::Printf("Final chunk header State:");
sl@0
  2489
		for (j=0; j<30; j+=8)
sl@0
  2490
 			Kern::Printf("%2x: %8x %8x %8x %8x %8x %8x %8x %8x", j, mem[j], mem[j+1], mem[j+2], mem[j+3], mem[j+4], mem[j+5], mem[j+6], mem[j+7] );
sl@0
  2491
		};
sl@0
  2492
	};
sl@0
  2493
#endif
sl@0
  2494
sl@0
  2495
sl@0
  2496
/*
sl@0
  2497
Chunk Created, filled with structure, and passed back to userside.
sl@0
  2498
*/
sl@0
  2499
TInt DLddUsbcScChannel::RealizeInterface(void)
sl@0
  2500
{
sl@0
  2501
	if (iRealizeCalled) 
sl@0
  2502
		return KErrUsbAlreadyRealized;
sl@0
  2503
sl@0
  2504
	TRealizeInfo bufInfo;
sl@0
  2505
	
sl@0
  2506
	TInt errorOrChunk = KErrNone;
sl@0
  2507
	TBool openedCS = EFalse;
sl@0
  2508
	TInt offset =0;
sl@0
  2509
		
sl@0
  2510
	// Start by creating a temporary scratchpad for endpoint calculations.
sl@0
  2511
	bufInfo.Init(iAlternateSettingList);
sl@0
  2512
sl@0
  2513
	// Fill in our scratchpad with all the required endpoints, sorting them
sl@0
  2514
	// in order of size required.
sl@0
  2515
	errorOrChunk = bufInfo.CopyAndSortEndpoints();
sl@0
  2516
	if (errorOrChunk!=KErrNone)
sl@0
  2517
		{
sl@0
  2518
		goto realize_end;
sl@0
  2519
		}
sl@0
  2520
sl@0
  2521
	// We now have endpoints sorted in order of size for each altsetting.
sl@0
  2522
	// The very largest for each endpoint will share the first buffer, and all of
sl@0
  2523
	// the second largest ends points will share the second buffer, and so on.
sl@0
  2524
	// Find the highest buffer size for each row, to determine the buffer size,
sl@0
  2525
	// and keep a total of total space needed. 
sl@0
  2526
	bufInfo.CalcBuffSizes();
sl@0
  2527
sl@0
  2528
	// We now have the max sizes wanted for each endpoint buffer.
sl@0
  2529
	// we also have to total size for all endpoints.
sl@0
  2530
	// and finally we have the total number of buffers.
sl@0
  2531
sl@0
  2532
	// Add on size for header, then add on size for guard pages.
sl@0
  2533
	bufInfo.iTotalSize+= KHeaderSize + bufInfo.iTotalBuffers * KGuardSize;
sl@0
  2534
sl@0
  2535
	// Create shared Chunk .  .  .  .  .  .  .  .  .  . 
sl@0
  2536
	if (iChunkInfo==NULL)
sl@0
  2537
		{
sl@0
  2538
			NKern::ThreadEnterCS();
sl@0
  2539
			openedCS = ETrue;
sl@0
  2540
			errorOrChunk = TUsbcScChunkInfo::New(iChunkInfo, bufInfo.iTotalSize, (DLogicalDevice*) iDevice);
sl@0
  2541
			if (errorOrChunk!=KErrNone)
sl@0
  2542
				{
sl@0
  2543
				goto realize_end;
sl@0
  2544
				}
sl@0
  2545
		}
sl@0
  2546
	else
sl@0
  2547
		{
sl@0
  2548
		// As of writing, the was no way for iChunk to be anything other then NULL.  
sl@0
  2549
		// You cannot 'unrealise' and iChunk cannot be set any other way.
sl@0
  2550
		Kern::Fault("DLddUsbcScChannel::RealizeInterface", __LINE__);
sl@0
  2551
		}
sl@0
  2552
sl@0
  2553
	// Populate the shared chunk . .  . . . . . 
sl@0
  2554
sl@0
  2555
sl@0
  2556
	// First create chunk header.
sl@0
  2557
	errorOrChunk = iChunkInfo->ChunkAlloc(offset, KHeaderSize);
sl@0
  2558
	if (errorOrChunk!=KErrNone)
sl@0
  2559
		{
sl@0
  2560
		if (errorOrChunk==-KErrNoMemory)
sl@0
  2561
			errorOrChunk=KErrNoMemory;
sl@0
  2562
		goto realize_end;
sl@0
  2563
		} 
sl@0
  2564
sl@0
  2565
sl@0
  2566
	offset+=KHeaderSize + KGuardSize; // Also any more for EP0?
sl@0
  2567
sl@0
  2568
	// Next, lay out the geometry of the chunk header.
sl@0
  2569
sl@0
  2570
	bufInfo.LayoutChunkHeader(iChunkInfo);		
sl@0
  2571
sl@0
  2572
sl@0
  2573
	{ // Scope ep0Size
sl@0
  2574
	TInt ep0Size=0;
sl@0
  2575
	
sl@0
  2576
	// Create K-side buffer table
sl@0
  2577
	if (!iBuffers)
sl@0
  2578
		iBuffers = (TUsbcScBuffer *) Kern::AllocZ(sizeof(TUsbcScBuffer) * (bufInfo.iTotalBuffers+2)); // +2 is for ep0.
sl@0
  2579
	if (!iBuffers)
sl@0
  2580
		{
sl@0
  2581
		__KTRACE_OPT(KUSB, Kern::Printf("Realize: Error: Alloc iBufers failed!"));
sl@0
  2582
		errorOrChunk = KErrNoMemory;
sl@0
  2583
		goto realize_end;
sl@0
  2584
		}
sl@0
  2585
sl@0
  2586
sl@0
  2587
	errorOrChunk = SetupEp0();
sl@0
  2588
	if (errorOrChunk)
sl@0
  2589
		{
sl@0
  2590
		__KTRACE_OPT(KUSB, Kern::Printf("Realize: SetupEp0 . ERROR %d",errorOrChunk));
sl@0
  2591
		goto realize_end;
sl@0
  2592
		}
sl@0
  2593
sl@0
  2594
	ep0Size = iEp0Endpoint->EndpointInfo()->iSize;
sl@0
  2595
	__KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0. max packet size %d", ep0Size));
sl@0
  2596
sl@0
  2597
	// Create EP0 buffers
sl@0
  2598
	iEP0OutBuff=bufInfo.iTotalBuffers;
sl@0
  2599
	errorOrChunk = iBuffers[iEP0OutBuff].Construct(KUsbcScBiOut,  this,   KUsbScEP0OutBufPos, KUsbScEP0OutBufEnd, ep0Size, ep0Size, ep0Size);
sl@0
  2600
	if (errorOrChunk)
sl@0
  2601
		{
sl@0
  2602
		__KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0 Out. ERROR %d",errorOrChunk));
sl@0
  2603
		goto realize_end;
sl@0
  2604
		}
sl@0
  2605
sl@0
  2606
	iBuffers[iEP0OutBuff].CreateChunkBufferHeader();
sl@0
  2607
	iBuffers[iEP0OutBuff].iCallback =  iEp0Endpoint->iRequestCallbackInfo;
sl@0
  2608
	((TUsbcScBufferRecord*) &(
sl@0
  2609
							bufInfo.iChunkStuct->iBufferOffset[KUsbcScEp0OutBuff*sizeof(TUsbcScBufferRecord)]
sl@0
  2610
							)) ->Set(KUsbScEP0OutBufPos, KUsbScEP0OutBufEnd);
sl@0
  2611
sl@0
  2612
sl@0
  2613
	iEP0InBuff=bufInfo.iTotalBuffers+1;
sl@0
  2614
	errorOrChunk = iBuffers[iEP0InBuff].Construct( KUsbcScBiIn ,  this,   KUsbScEP0InBufPos , KUsbScEP0InBufEnd , ep0Size, ep0Size, ep0Size);	
sl@0
  2615
	if (errorOrChunk)
sl@0
  2616
		{
sl@0
  2617
		__KTRACE_OPT(KUSB, Kern::Printf("Realize: Setup EP0 In. ERROR %d",errorOrChunk));
sl@0
  2618
		goto realize_end;
sl@0
  2619
		}
sl@0
  2620
	
sl@0
  2621
	iBuffers[iEP0InBuff].iCallback =  iEp0Endpoint->iRequestCallbackInfo;
sl@0
  2622
sl@0
  2623
	  ((TUsbcScBufferRecord*) &(
sl@0
  2624
	  							bufInfo.iChunkStuct->iBufferOffset[KUsbcScEp0InBuff*sizeof(TUsbcScBufferRecord)]
sl@0
  2625
								))->Set(KUsbScEP0InBufPos, KUsbScEP0InBufEnd);
sl@0
  2626
sl@0
  2627
sl@0
  2628
	} // end ep0Size scope
sl@0
  2629
sl@0
  2630
	// Create resources and tables.  .   .   .   .   .
sl@0
  2631
	__KTRACE_OPT(KUSB, Kern::Printf("Realize: Create resources tables"));
sl@0
  2632
sl@0
  2633
	{ // scope of bufNum
sl@0
  2634
	// For each EP buffer
sl@0
  2635
	TInt buffNum=0;
sl@0
  2636
	TInt buffMinSize;
sl@0
  2637
	TInt endpointNumber;
sl@0
  2638
	TUsbcScEndpoint* endpointRecord;
sl@0
  2639
	TInt endpoint;
sl@0
  2640
	TInt inout;
sl@0
  2641
	TEndpointSortBufs* bufsd;
sl@0
  2642
	TUsbcScHdrEndpointRecord* epRecord;
sl@0
  2643
	for (endpoint=0; endpoint<bufInfo.iMaxEndpoints; endpoint++)  // endpoint = buf row.
sl@0
  2644
		{
sl@0
  2645
		for (inout=KUsbcScIn; inout<KUsbcScDirections; inout++)
sl@0
  2646
			{
sl@0
  2647
			buffMinSize = KUsbSc_BigBuff_MinimumRamRun;
sl@0
  2648
sl@0
  2649
			TInt needed =  bufInfo.iBufs[inout].iSizes[endpoint];
sl@0
  2650
			if (needed) 
sl@0
  2651
				{
sl@0
  2652
				TInt bufStart = offset;
sl@0
  2653
sl@0
  2654
				__KTRACE_OPT(KUSB, Kern::Printf("Realize:    buf row:%d inout %d, iBufferOffset[%d+2]=%x",endpoint, inout, buffNum, bufStart));
sl@0
  2655
sl@0
  2656
				bufsd =  &(bufInfo.iBufs[inout]);
sl@0
  2657
				// and then point all endpoints that use it, towards it.
sl@0
  2658
				TInt altSetting;	
sl@0
  2659
				TUint maxReadSize = ~0;
sl@0
  2660
				for (altSetting=0; altSetting < bufInfo.iAltSettings; altSetting++)
sl@0
  2661
					{
sl@0
  2662
					endpointRecord =bufsd->iEp[altSetting*bufInfo.iMaxEndpoints + endpoint];
sl@0
  2663
					if (endpointRecord)
sl@0
  2664
						{
sl@0
  2665
						endpointNumber = endpointRecord->EpNumber();
sl@0
  2666
						endpointRecord->SetBuffer(&iBuffers[buffNum]);
sl@0
  2667
				
sl@0
  2668
						epRecord = (TUsbcScHdrEndpointRecord*) &iChunkInfo->iChunkMem[
sl@0
  2669
																(bufInfo.iAltSettingsTbl->iAltTableOffset[altSetting]) 	// i.e. Just after altSettingsTbl
sl@0
  2670
																+sizeof(TInt)									// after number of endpoints field
sl@0
  2671
																+(endpointNumber-1)*sizeof(TUsbcScHdrEndpointRecord)
sl@0
  2672
																];
sl@0
  2673
						epRecord->iBufferNo = (TUint8) buffNum;
sl@0
  2674
sl@0
  2675
					TInt epType=(endpointRecord->EndpointInfo()->iType);
sl@0
  2676
					epType= (epType& KUsbEpTypeControl)?KUsbScHdrEpTypeControl:
sl@0
  2677
							(epType& KUsbEpTypeIsochronous)?KUsbScHdrEpTypeIsochronous:
sl@0
  2678
							(epType& KUsbEpTypeBulk)?KUsbScHdrEpTypeBulk:
sl@0
  2679
							(epType& KUsbEpTypeInterrupt)?KUsbScHdrEpTypeInterrupt:KUsbScHdrEpTypeUnknown;
sl@0
  2680
sl@0
  2681
					epRecord->iType = (inout+1) | (epType<<2);
sl@0
  2682
sl@0
  2683
					if (endpointRecord->EndpointInfo()->iReadSize)
sl@0
  2684
						maxReadSize = (maxReadSize <= endpointRecord->EndpointInfo()->iReadSize) ? maxReadSize : endpointRecord->EndpointInfo()->iReadSize;
sl@0
  2685
					
sl@0
  2686
					__KTRACE_OPT(KUSB, Kern::Printf("Realize:      endpointNum %d in altSetting %d, alt table @ %d",
sl@0
  2687
													 endpointNumber, altSetting,bufInfo.iAltSettingsTbl->iAltTableOffset[altSetting]));
sl@0
  2688
						}
sl@0
  2689
					else
sl@0
  2690
						{
sl@0
  2691
						__KTRACE_OPT(KUSB, Kern::Printf("Realize:      endpointNum NA in altSetting %d", altSetting));
sl@0
  2692
						}
sl@0
  2693
sl@0
  2694
					} // end for
sl@0
  2695
sl@0
  2696
sl@0
  2697
				// Alloc memory for buffer.
sl@0
  2698
				TInt grabSize = needed;
sl@0
  2699
				// Generally, a buffer fragmented into smaller memory regions will reduce the efficiency 
sl@0
  2700
				// of reading or writing data, and so avoiding the allocation of very small sections
sl@0
  2701
				// is advantageous.
sl@0
  2702
				// However, if only a small amount is being allocated to start with, it is likely
sl@0
  2703
				// smaller amounts of data are to be sent (reducing this advantage), and 1 memory page 
sl@0
  2704
				// is a much bigger proportion of the buffer, and so more worth allocating individually.
sl@0
  2705
sl@0
  2706
				TInt minimumGrab;
sl@0
  2707
				if (needed<KUsbScBigBuffIs)
sl@0
  2708
					{
sl@0
  2709
					minimumGrab=Kern::RoundToPageSize(1);
sl@0
  2710
					buffMinSize = KUsbSc_SmallBuff_MinimumRamRun; // 1k
sl@0
  2711
					}
sl@0
  2712
				else
sl@0
  2713
					{
sl@0
  2714
					minimumGrab = buffMinSize+Kern::RoundToPageSize(1);
sl@0
  2715
					}
sl@0
  2716
sl@0
  2717
				// Grab required memory, in bits as big as possible, down to the minimum size. 
sl@0
  2718
				while (needed >= minimumGrab)
sl@0
  2719
					{
sl@0
  2720
					TInt r;
sl@0
  2721
					r = iChunkInfo->ChunkAlloc(offset, grabSize);
sl@0
  2722
					if (r==KErrNone)
sl@0
  2723
						{
sl@0
  2724
						offset+=grabSize;	
sl@0
  2725
						needed-=grabSize;
sl@0
  2726
						}
sl@0
  2727
					else
sl@0
  2728
						{
sl@0
  2729
						if (r==-KErrNoMemory)
sl@0
  2730
							{
sl@0
  2731
							grabSize>>=1;
sl@0
  2732
							}
sl@0
  2733
						if ((grabSize<minimumGrab) || (r!=-KErrNoMemory))
sl@0
  2734
							{
sl@0
  2735
							errorOrChunk = r;
sl@0
  2736
							goto realize_end;
sl@0
  2737
							}
sl@0
  2738
						}
sl@0
  2739
					} // end while needed
sl@0
  2740
				
sl@0
  2741
				// Initialize buffer
sl@0
  2742
				iBuffers[buffNum].Construct(inout,  this,   bufStart, offset, buffMinSize, 0, maxReadSize);
sl@0
  2743
				iBuffers[buffNum].CreateChunkBufferHeader();
sl@0
  2744
				((TUsbcScBufferRecord*) &(
sl@0
  2745
										bufInfo.iChunkStuct->iBufferOffset[(buffNum+2)*sizeof(TUsbcScBufferRecord)]
sl@0
  2746
										))->Set(bufStart, offset);
sl@0
  2747
sl@0
  2748
sl@0
  2749
				// inc pointers for next buffer
sl@0
  2750
				buffNum++;
sl@0
  2751
				offset+=KGuardSize;
sl@0
  2752
				} // end if needed
sl@0
  2753
sl@0
  2754
			} // end for inout
sl@0
  2755
		} // end for each buffer
sl@0
  2756
	} // scope of bufNum 
sl@0
  2757
sl@0
  2758
#ifdef _DEBUG
sl@0
  2759
 RealizeInterface_Dump((TUint*) iChunkInfo->iChunkMem); // Debug only tracing
sl@0
  2760
#endif
sl@0
  2761
sl@0
  2762
realize_end:
sl@0
  2763
	__KTRACE_OPT(KUSB, Kern::Printf("Realize: cleanup.  Err=%d", errorOrChunk));
sl@0
  2764
	// Here we clean up after either success, or after bailing out early.
sl@0
  2765
sl@0
  2766
	bufInfo.Free();
sl@0
  2767
	
sl@0
  2768
	if (iChunkInfo)
sl@0
  2769
		{
sl@0
  2770
		if (errorOrChunk==KErrNone)
sl@0
  2771
			{ 
sl@0
  2772
			// Everything is looking good - create RChunk for Userside.
sl@0
  2773
			errorOrChunk = Kern::MakeHandleAndOpen(iClient, iChunkInfo->iChunk);
sl@0
  2774
			iRealizeCalled = (errorOrChunk>=0);
sl@0
  2775
			} // endif errorOrChunk
sl@0
  2776
sl@0
  2777
		if (errorOrChunk<0)  // If error, destroy the chunk.
sl@0
  2778
			{
sl@0
  2779
			iChunkInfo->Close();
sl@0
  2780
			// ChunkInfo will delete itself with DFC, but the pointer here is no longer needed.
sl@0
  2781
			iChunkInfo=NULL;
sl@0
  2782
sl@0
  2783
			// Destroy iBuffers
sl@0
  2784
			if (iBuffers)
sl@0
  2785
				{
sl@0
  2786
				TInt i;
sl@0
  2787
				for (i=0; i<(iNumBuffers+2); i++) 
sl@0
  2788
					{
sl@0
  2789
					iBuffers[i].iStatusList.Destroy();
sl@0
  2790
					}
sl@0
  2791
				Kern::Free(iBuffers);
sl@0
  2792
				iBuffers=NULL;
sl@0
  2793
				}
sl@0
  2794
sl@0
  2795
			}
sl@0
  2796
		else
sl@0
  2797
			{
sl@0
  2798
			iNumBuffers = bufInfo.iTotalBuffers;
sl@0
  2799
			iValidInterface = ETrue;  // Let the games commence!
sl@0
  2800
			}
sl@0
  2801
sl@0
  2802
		} // endif iChunkInfo
sl@0
  2803
	if (openedCS)
sl@0
  2804
		NKern::ThreadLeaveCS();
sl@0
  2805
sl@0
  2806
	__KTRACE_OPT(KUSB, Kern::Printf("Realize: returning %x (%d)", errorOrChunk, errorOrChunk));
sl@0
  2807
	return errorOrChunk;
sl@0
  2808
} // End RealizeInterface
sl@0
  2809
sl@0
  2810
sl@0
  2811
//
sl@0
  2812
// DestroyAllInterfaces
sl@0
  2813
//
sl@0
  2814
sl@0
  2815
void DLddUsbcScChannel::DestroyAllInterfaces()
sl@0
  2816
	{
sl@0
  2817
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyAllInterfaces"));
sl@0
  2818
	// Removes all interfaces
sl@0
  2819
	if (iAlternateSettingList)
sl@0
  2820
		{
sl@0
  2821
		if (iAlternateSettingList->iHead != NULL)
sl@0
  2822
			{
sl@0
  2823
			TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iTail;
sl@0
  2824
			while (alternateSettingListRec)
sl@0
  2825
				{
sl@0
  2826
				iAlternateSettingList->iTail = alternateSettingListRec->iPrevious; 
sl@0
  2827
				// If this contains NULL now that is only possible if the record to be deleted was at the head
sl@0
  2828
				__KTRACE_OPT(KUSB, Kern::Printf("Release interface %d \n", alternateSettingListRec->iSetting));
sl@0
  2829
				iController->ReleaseInterface(this, alternateSettingListRec->iSetting);
sl@0
  2830
				delete alternateSettingListRec;
sl@0
  2831
				if (iAlternateSettingList->iTail == NULL) //No more interfaces left 
sl@0
  2832
					break;
sl@0
  2833
				else
sl@0
  2834
					{
sl@0
  2835
					iAlternateSettingList->iTail->iNext = NULL;
sl@0
  2836
					alternateSettingListRec = iAlternateSettingList->iTail;
sl@0
  2837
					}
sl@0
  2838
				}
sl@0
  2839
			}
sl@0
  2840
		delete iAlternateSettingList;	
sl@0
  2841
		}
sl@0
  2842
sl@0
  2843
	iNumberOfEndpoints = 0;
sl@0
  2844
	iAlternateSettingList = NULL;
sl@0
  2845
	iValidInterface = EFalse;
sl@0
  2846
sl@0
  2847
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyAllInterfaces done"));
sl@0
  2848
	}
sl@0
  2849
sl@0
  2850
sl@0
  2851
		
sl@0
  2852
sl@0
  2853
sl@0
  2854
//
sl@0
  2855
// DestroyInterface
sl@0
  2856
//
sl@0
  2857
sl@0
  2858
void DLddUsbcScChannel::DestroyInterface(TUint aInterfaceNumber)
sl@0
  2859
	{
sl@0
  2860
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyInterface \n"));
sl@0
  2861
	
sl@0
  2862
	if (iAlternateSetting == aInterfaceNumber)
sl@0
  2863
		{
sl@0
  2864
		ResetInterface(KErrUsbInterfaceNotReady);
sl@0
  2865
		iValidInterface = EFalse;
sl@0
  2866
		iNumberOfEndpoints = 0;
sl@0
  2867
		}
sl@0
  2868
	if (iAlternateSettingList)
sl@0
  2869
		{
sl@0
  2870
		TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iTail;
sl@0
  2871
		TUsbcScAlternateSetting* alternateSettingListRecFound = NULL;
sl@0
  2872
		while (alternateSettingListRec)
sl@0
  2873
			{
sl@0
  2874
			if (alternateSettingListRec->iSetting == aInterfaceNumber)
sl@0
  2875
				{
sl@0
  2876
				alternateSettingListRecFound = alternateSettingListRec;
sl@0
  2877
				if (alternateSettingListRec->iPrevious == NULL)	//Interface is at HEAD OF List, Should only be if Interface is also at Tail of list
sl@0
  2878
					{
sl@0
  2879
					iAlternateSettingList->iHead = alternateSettingListRec->iNext;	// Should be NULL
sl@0
  2880
					if (alternateSettingListRec->iNext)
sl@0
  2881
						iAlternateSettingList->iHead->iPrevious = NULL;
sl@0
  2882
					}
sl@0
  2883
				else if (alternateSettingListRec->iNext == NULL) //Interface is at TAIL OF List
sl@0
  2884
					{
sl@0
  2885
					iAlternateSettingList->iTail = alternateSettingListRecFound->iPrevious;
sl@0
  2886
					iAlternateSettingList->iTail->iNext = NULL;
sl@0
  2887
					}
sl@0
  2888
				else	//Somewhere in the middle (would not expect this in normal operation, but here for completeness)
sl@0
  2889
					{
sl@0
  2890
					__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DestroyInterface Middle interface!\n"));
sl@0
  2891
					alternateSettingListRec->iPrevious->iNext = alternateSettingListRec->iNext;
sl@0
  2892
					alternateSettingListRec->iNext->iPrevious = alternateSettingListRec->iPrevious;
sl@0
  2893
					}	
sl@0
  2894
sl@0
  2895
				delete alternateSettingListRecFound;
sl@0
  2896
				break;
sl@0
  2897
				}
sl@0
  2898
 			alternateSettingListRec = alternateSettingListRec->iPrevious;
sl@0
  2899
			}
sl@0
  2900
		}
sl@0
  2901
	}
sl@0
  2902
sl@0
  2903
//
sl@0
  2904
// SetupEp0
sl@0
  2905
//
sl@0
  2906
sl@0
  2907
TInt DLddUsbcScChannel::SetupEp0()
sl@0
  2908
	{
sl@0
  2909
	__ASSERT_ALWAYS(iEp0Endpoint==NULL, Kern::Fault("DLddUsbcScChannel::SetupEp0", __LINE__));
sl@0
  2910
sl@0
  2911
	TUsbcScEndpointInfo ep0Info = TUsbcScEndpointInfo(KUsbEpTypeControl, KUsbEpDirBidirect);
sl@0
  2912
	ep0Info.iSize =  iController->Ep0PacketSize();
sl@0
  2913
sl@0
  2914
	TUsbcScEndpoint* ep0 = new TUsbcScEndpoint(this, iController, &ep0Info, 0);
sl@0
  2915
	if (ep0 == NULL)
sl@0
  2916
		{
sl@0
  2917
		return KErrNoMemory;
sl@0
  2918
		}
sl@0
  2919
sl@0
  2920
	TInt r = ep0->Construct();
sl@0
  2921
	if (r != KErrNone)
sl@0
  2922
		{
sl@0
  2923
		delete ep0;
sl@0
  2924
		return KErrNoMemory;
sl@0
  2925
		}
sl@0
  2926
sl@0
  2927
	ep0->SetRealEpNumber(0);
sl@0
  2928
	ep0->SetBuffer(NULL); // Cannot find it this way.
sl@0
  2929
sl@0
  2930
	iEp0Endpoint = ep0;
sl@0
  2931
	return KErrNone;
sl@0
  2932
	}
sl@0
  2933
sl@0
  2934
//
sl@0
  2935
// DestroyEp0
sl@0
  2936
//
sl@0
  2937
sl@0
  2938
void DLddUsbcScChannel::DestroyEp0()
sl@0
  2939
	{
sl@0
  2940
	__KTRACE_OPT(KUSB, Kern::Printf(" DLddUsbcScChannel::DestroyEp0"));
sl@0
  2941
	delete iEp0Endpoint;
sl@0
  2942
	iEp0Endpoint = NULL;
sl@0
  2943
	}
sl@0
  2944
sl@0
  2945
sl@0
  2946
void DLddUsbcScChannel::RequestCallbackEp0(TAny* aDLddUsbcScChannel)
sl@0
  2947
    {
sl@0
  2948
	DLddUsbcScChannel* channel = (DLddUsbcScChannel*) aDLddUsbcScChannel;
sl@0
  2949
sl@0
  2950
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::RequestCallbackEp0"));
sl@0
  2951
sl@0
  2952
	if (channel->ChannelClosing())
sl@0
  2953
		{
sl@0
  2954
		__KTRACE_OPT(KUSB, Kern::Printf("Channel Closing: Completion not accepted!"));
sl@0
  2955
		return;
sl@0
  2956
		}
sl@0
  2957
sl@0
  2958
	switch (channel->iEp0Endpoint->iRequestCallbackInfo->iTransferDir)
sl@0
  2959
		{
sl@0
  2960
	case EControllerWrite:
sl@0
  2961
		channel->iBuffers[channel->iEP0InBuff].CompleteWrite();
sl@0
  2962
		return;
sl@0
  2963
	case EControllerRead:
sl@0
  2964
		channel->iBuffers[channel->iEP0OutBuff].CompleteRead();
sl@0
  2965
		return;
sl@0
  2966
	default:
sl@0
  2967
		Kern::Printf("DLddUsbcScChannel::RequestCallbackEp0 - Unexpected completion direction %d",channel->iEp0Endpoint->iRequestCallbackInfo->iTransferDir);
sl@0
  2968
		Kern::Fault("DLddUsbcScChannel::RequestCallbackEp0", __LINE__);
sl@0
  2969
		} 
sl@0
  2970
	}
sl@0
  2971
sl@0
  2972
sl@0
  2973
sl@0
  2974
sl@0
  2975
sl@0
  2976
sl@0
  2977
//
sl@0
  2978
// EndpointStatusChangeCallback
sl@0
  2979
//
sl@0
  2980
sl@0
  2981
void DLddUsbcScChannel::EndpointStatusChangeCallback(TAny* aDLddUsbcScChannel)
sl@0
  2982
    {
sl@0
  2983
	__KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback"));
sl@0
  2984
    DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
sl@0
  2985
	if (dUsbc->iChannelClosing)
sl@0
  2986
		return;
sl@0
  2987
	TUint endpointState = dUsbc->iEndpointStatusCallbackInfo.State();
sl@0
  2988
	const TInt reqNo = (TInt) RDevUsbcScClient::ERequestEndpointStatusNotify;
sl@0
  2989
	if (dUsbc->iRequestStatus[reqNo])
sl@0
  2990
		{
sl@0
  2991
		__KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback Notify status"));
sl@0
  2992
		DThread* client = dUsbc->iClient;
sl@0
  2993
		// set client descriptor length to zero
sl@0
  2994
		TInt r = Kern::ThreadRawWrite(client, dUsbc->iEndpointStatusChangePtr, &endpointState,
sl@0
  2995
									  sizeof(TUint), client);
sl@0
  2996
		if (r != KErrNone)
sl@0
  2997
			dUsbc->PanicClientThread(r);
sl@0
  2998
		Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], r);
sl@0
  2999
		dUsbc->iEndpointStatusChangePtr = NULL;
sl@0
  3000
		}
sl@0
  3001
	}
sl@0
  3002
sl@0
  3003
sl@0
  3004
//
sl@0
  3005
// StatusChangeCallback
sl@0
  3006
//
sl@0
  3007
sl@0
  3008
void DLddUsbcScChannel::StatusChangeCallback(TAny* aDLddUsbcScChannel)
sl@0
  3009
	{
sl@0
  3010
    DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
sl@0
  3011
	if (dUsbc->iChannelClosing)
sl@0
  3012
		return;
sl@0
  3013
sl@0
  3014
    TUsbcDeviceState deviceState;
sl@0
  3015
    TInt i;
sl@0
  3016
 	for (i = 0;
sl@0
  3017
 		 (i < KUsbcDeviceStateRequests) && ((deviceState = dUsbc->iStatusCallbackInfo.State(i)) != EUsbcNoState);
sl@0
  3018
 		 ++i)
sl@0
  3019
		{
sl@0
  3020
 		__KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallBack status=%d", deviceState));
sl@0
  3021
		if (deviceState & KUsbAlternateSetting)
sl@0
  3022
			{
sl@0
  3023
			dUsbc->ProcessAlternateSetting(deviceState);
sl@0
  3024
			}
sl@0
  3025
		else
sl@0
  3026
			{
sl@0
  3027
			dUsbc->ProcessDeviceState(deviceState);
sl@0
  3028
			// Send Status to EP0 buffer.		
sl@0
  3029
			dUsbc->iBuffers[dUsbc->iEP0OutBuff].SendEp0StatusPacket(deviceState);
sl@0
  3030
			}
sl@0
  3031
sl@0
  3032
		// Only queue if userside is interested
sl@0
  3033
		if (dUsbc->iDeviceStatusNeeded)
sl@0
  3034
			{
sl@0
  3035
			dUsbc->iStatusFifo->AddStatusToQueue(deviceState);
sl@0
  3036
			const TInt reqNo = (TInt) RDevUsbcScClient::ERequestAlternateDeviceStatusNotify;
sl@0
  3037
			if (dUsbc->AlternateDeviceStateTestComplete())
sl@0
  3038
				Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], KErrNone);
sl@0
  3039
			}
sl@0
  3040
		}
sl@0
  3041
 	// We don't want to be interrupted in the middle of this:
sl@0
  3042
	const TInt irqs = NKern::DisableInterrupts(2);
sl@0
  3043
 	dUsbc->iStatusCallbackInfo.ResetState();
sl@0
  3044
	NKern::RestoreInterrupts(irqs);
sl@0
  3045
	}
sl@0
  3046
sl@0
  3047
sl@0
  3048
void DLddUsbcScChannel::OtgFeatureChangeCallback(TAny* aDLddUsbcScChannel)
sl@0
  3049
    {
sl@0
  3050
	__KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback"));
sl@0
  3051
    DLddUsbcScChannel* dUsbc = (DLddUsbcScChannel*) aDLddUsbcScChannel;
sl@0
  3052
	if (dUsbc->iChannelClosing)
sl@0
  3053
		return;
sl@0
  3054
sl@0
  3055
    TUint8 features;
sl@0
  3056
    // No return value check. Assume OTG always supported here
sl@0
  3057
    dUsbc->iController->GetCurrentOtgFeatures(features);
sl@0
  3058
sl@0
  3059
    const TInt reqNo = (TInt) RDevUsbcScClient::ERequestOtgFeaturesNotify;
sl@0
  3060
	if (dUsbc->iRequestStatus[reqNo])
sl@0
  3061
		{
sl@0
  3062
		__KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback Notify status"));
sl@0
  3063
		TInt r = Kern::ThreadRawWrite(dUsbc->iClient, dUsbc->iOtgFeatureChangePtr,
sl@0
  3064
                                      &features, sizeof(TUint8), dUsbc->iClient);
sl@0
  3065
		if (r != KErrNone)
sl@0
  3066
			dUsbc->PanicClientThread(r);
sl@0
  3067
		Kern::RequestComplete(dUsbc->iClient, dUsbc->iRequestStatus[reqNo], r);
sl@0
  3068
		dUsbc->iOtgFeatureChangePtr = NULL;
sl@0
  3069
		}
sl@0
  3070
    }
sl@0
  3071
sl@0
  3072
sl@0
  3073
//
sl@0
  3074
// SelectAlternateSetting
sl@0
  3075
//
sl@0
  3076
sl@0
  3077
TInt DLddUsbcScChannel::SelectAlternateSetting(TUint aAlternateSetting)
sl@0
  3078
	{
sl@0
  3079
	TUsbcScEndpoint* ep;
sl@0
  3080
sl@0
  3081
	// First, find the alt setting record, which corresponds to the alt setting number.
sl@0
  3082
	TUsbcScAlternateSetting* alternateSettingListRec;
sl@0
  3083
	if(iAlternateSettingList)
sl@0
  3084
		{
sl@0
  3085
		for (alternateSettingListRec = iAlternateSettingList->iHead; alternateSettingListRec; alternateSettingListRec = alternateSettingListRec->iNext)
sl@0
  3086
			if (alternateSettingListRec->iSetting == aAlternateSetting)
sl@0
  3087
				{
sl@0
  3088
				// Record has been located.
sl@0
  3089
sl@0
  3090
				// Update current ep setting vars 
sl@0
  3091
				iEndpoint = alternateSettingListRec->iEndpoint;
sl@0
  3092
				iNumberOfEndpoints = alternateSettingListRec->iNumberOfEndpoints;
sl@0
  3093
sl@0
  3094
sl@0
  3095
sl@0
  3096
				// Reset buffers for new ep set
sl@0
  3097
				for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
sl@0
  3098
					{
sl@0
  3099
					ep = alternateSettingListRec->iEndpoint[i];
sl@0
  3100
					if (ep!=NULL)
sl@0
  3101
						ep->StartBuffer(); // Buffer::StartEndpoint(...)   sets the necessary parameters to the buffer, for use for a perticular endpoint.
sl@0
  3102
					}
sl@0
  3103
sl@0
  3104
				return KErrNone;
sl@0
  3105
				}
sl@0
  3106
		}
sl@0
  3107
	return KErrGeneral;
sl@0
  3108
	}
sl@0
  3109
sl@0
  3110
/* The user calls this to move into the next alternate setting.  After this call, it is assumed the user wants to
sl@0
  3111
Transmit using endpoints belonging to this alternate Setting.  Writes to the IN endpoints will be allowed until
sl@0
  3112
the host changed the alternate setting again
sl@0
  3113
Returns a 32 int with the top 16 bits represents the sequance, and the botten, the alternatre setting no.
sl@0
  3114
*/
sl@0
  3115
TInt32 DLddUsbcScChannel::StartNextInAlternateSetting()
sl@0
  3116
	{
sl@0
  3117
	iUserKnowsAltSetting = ETrue;
sl@0
  3118
	return iAsSeq<<16 | iAlternateSetting;
sl@0
  3119
	} 
sl@0
  3120
sl@0
  3121
sl@0
  3122
//
sl@0
  3123
// EpFromAlternateSetting
sl@0
  3124
//
sl@0
  3125
sl@0
  3126
TInt DLddUsbcScChannel::EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint)
sl@0
  3127
	{
sl@0
  3128
	TUsbcScAlternateSetting* alternateSettingListRec = iAlternateSettingList->iHead;
sl@0
  3129
	while (alternateSettingListRec)
sl@0
  3130
		{
sl@0
  3131
		if (alternateSettingListRec->iSetting == aAlternateSetting)
sl@0
  3132
			{
sl@0
  3133
			if ((aEndpoint <= alternateSettingListRec->iNumberOfEndpoints) &&
sl@0
  3134
				(aEndpoint > 0))
sl@0
  3135
				{
sl@0
  3136
				return alternateSettingListRec->iEndpoint[aEndpoint]->RealEpNumber();
sl@0
  3137
				}
sl@0
  3138
			else
sl@0
  3139
				{
sl@0
  3140
				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: aEndpoint %d wrong for aAlternateSetting %d",
sl@0
  3141
												  aEndpoint, aAlternateSetting));
sl@0
  3142
				return KErrNotFound;
sl@0
  3143
				}
sl@0
  3144
			}
sl@0
  3145
		alternateSettingListRec = alternateSettingListRec->iNext;
sl@0
  3146
		}
sl@0
  3147
	__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no aAlternateSetting %d found", aAlternateSetting));
sl@0
  3148
	return KErrNotFound;
sl@0
  3149
	}
sl@0
  3150
sl@0
  3151
//
sl@0
  3152
// ProcessAlternateSetting
sl@0
  3153
//
sl@0
  3154
sl@0
  3155
TInt DLddUsbcScChannel::ProcessAlternateSetting(TUint aAlternateSetting)
sl@0
  3156
	{
sl@0
  3157
sl@0
  3158
	TUint newSetting = aAlternateSetting&(~KUsbAlternateSetting);
sl@0
  3159
	__KTRACE_OPT(KUSB, Kern::Printf("ProcessAlternateSetting 0x%08x selecting alternate setting 0x%08x", aAlternateSetting, newSetting));
sl@0
  3160
	iUserKnowsAltSetting=EFalse;
sl@0
  3161
	iAlternateSetting = newSetting;
sl@0
  3162
	iAsSeq++; 
sl@0
  3163
	
sl@0
  3164
	ResetInterface(KErrUsbInterfaceChange);					// kill any outstanding IN transfers
sl@0
  3165
sl@0
  3166
	TInt r = SelectAlternateSetting(newSetting);
sl@0
  3167
	if (r != KErrNone)
sl@0
  3168
		return r;
sl@0
  3169
sl@0
  3170
sl@0
  3171
	StartEpReads();
sl@0
  3172
    return KErrNone;
sl@0
  3173
	}
sl@0
  3174
sl@0
  3175
sl@0
  3176
//
sl@0
  3177
//  ProcessDeviceState
sl@0
  3178
//
sl@0
  3179
// Called from StatusChangeCallback.
sl@0
  3180
sl@0
  3181
TInt DLddUsbcScChannel::ProcessDeviceState(TUsbcDeviceState aDeviceState)
sl@0
  3182
	{
sl@0
  3183
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::ProcessDeviceState(%d -> %d)", iDeviceState, aDeviceState));
sl@0
  3184
	if (iDeviceState == aDeviceState)
sl@0
  3185
		{
sl@0
  3186
		__KTRACE_OPT(KUSB, Kern::Printf("  No state change => nothing to be done."));
sl@0
  3187
		return KErrNone;
sl@0
  3188
		}
sl@0
  3189
	if (iDeviceState == EUsbcDeviceStateSuspended)
sl@0
  3190
		{
sl@0
  3191
		__KTRACE_OPT(KUSB, Kern::Printf("  Coming out of Suspend: old state = %d", iOldDeviceState));
sl@0
  3192
		iDeviceState = iOldDeviceState;
sl@0
  3193
		if (iDeviceState == aDeviceState)
sl@0
  3194
			{
sl@0
  3195
			__KTRACE_OPT(KUSB, Kern::Printf("  New state same as before Suspend => nothing to be done."));
sl@0
  3196
			return KErrNone;
sl@0
  3197
			}
sl@0
  3198
		}
sl@0
  3199
	TBool renumerateState = (aDeviceState == EUsbcDeviceStateConfigured);
sl@0
  3200
	TBool deconfigured = EFalse;
sl@0
  3201
	TInt cancellationCode = KErrNone;
sl@0
  3202
	if (aDeviceState == EUsbcDeviceStateSuspended)
sl@0
  3203
		{
sl@0
  3204
		__KTRACE_OPT(KUSB, Kern::Printf("  Suspending..."));
sl@0
  3205
		iOldDeviceState = iDeviceState;
sl@0
  3206
		// Put PSL into low power mode here
sl@0
  3207
		}
sl@0
  3208
	else
sl@0
  3209
		{
sl@0
  3210
		deconfigured = (iDeviceState == EUsbcDeviceStateConfigured &&
sl@0
  3211
						aDeviceState != EUsbcDeviceStateConfigured);
sl@0
  3212
		if (iDeviceState == EUsbcDeviceStateConfigured)
sl@0
  3213
			{
sl@0
  3214
			if (aDeviceState == EUsbcDeviceStateUndefined)
sl@0
  3215
				cancellationCode = KErrUsbCableDetached;
sl@0
  3216
			else if (aDeviceState == EUsbcDeviceStateAddress)
sl@0
  3217
				cancellationCode = KErrUsbDeviceNotConfigured;
sl@0
  3218
			else if (aDeviceState == EUsbcDeviceStateDefault)
sl@0
  3219
				cancellationCode = KErrUsbDeviceBusReset;
sl@0
  3220
			else
sl@0
  3221
				cancellationCode = KErrUsbDeviceNotConfigured;
sl@0
  3222
			}
sl@0
  3223
		}
sl@0
  3224
	iDeviceState = aDeviceState;
sl@0
  3225
	if (iValidInterface || iOwnsDeviceControl)
sl@0
  3226
		{
sl@0
  3227
sl@0
  3228
		// This LDD may not own an interface. It could be some manager reenumerating
sl@0
  3229
		// after its subordinate LDDs have setup their interfaces.
sl@0
  3230
		if (deconfigured)
sl@0
  3231
			{
sl@0
  3232
		    DeConfigure(cancellationCode);
sl@0
  3233
			}
sl@0
  3234
		else if (renumerateState)
sl@0
  3235
			{
sl@0
  3236
 			__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChannel:: Reumerated!"));
sl@0
  3237
			// Select main interface & latch in new endpoint set
sl@0
  3238
			SelectAlternateSetting(0);
sl@0
  3239
			__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChannel:: StartReads!"));
sl@0
  3240
			StartEpReads();
sl@0
  3241
			}
sl@0
  3242
		}
sl@0
  3243
sl@0
  3244
	const TInt reqNo = (TInt) RDevUsbcScClient::ERequestReEnumerate;
sl@0
  3245
	if (renumerateState && iRequestStatus[reqNo])
sl@0
  3246
		{
sl@0
  3247
		// This lot must be done if we are reenumerated
sl@0
  3248
		Kern::RequestComplete(iClient, iRequestStatus[reqNo], KErrNone);
sl@0
  3249
		}
sl@0
  3250
sl@0
  3251
    return KErrNone;
sl@0
  3252
    }
sl@0
  3253
sl@0
  3254
sl@0
  3255
TBool DLddUsbcScChannel::AlternateDeviceStateTestComplete()
sl@0
  3256
	{
sl@0
  3257
	TBool completeNow = EFalse;
sl@0
  3258
	const TInt reqNo = (TInt) RDevUsbcScClient::ERequestAlternateDeviceStatusNotify;
sl@0
  3259
	if (iRequestStatus[reqNo])
sl@0
  3260
		{
sl@0
  3261
		// User req is outstanding
sl@0
  3262
		TUint32 deviceState;
sl@0
  3263
		if (iStatusFifo->GetDeviceQueuedStatus(deviceState) == KErrNone)
sl@0
  3264
			{
sl@0
  3265
			// Device state waiting to be sent userside
sl@0
  3266
			completeNow = ETrue;
sl@0
  3267
			__KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallback Notify status"));
sl@0
  3268
			// set client descriptor length to zero
sl@0
  3269
			TInt r = Kern::ThreadRawWrite(iClient, iStatusChangePtr, &deviceState,
sl@0
  3270
										  sizeof(TUint32), iClient);
sl@0
  3271
			if (r != KErrNone)
sl@0
  3272
				PanicClientThread(r);
sl@0
  3273
			iStatusChangePtr = NULL;
sl@0
  3274
			}
sl@0
  3275
		}
sl@0
  3276
	return completeNow;
sl@0
  3277
	}
sl@0
  3278
sl@0
  3279
sl@0
  3280
void DLddUsbcScChannel::DeConfigure(TInt aErrorCode)
sl@0
  3281
	{
sl@0
  3282
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DeConfigure()"));
sl@0
  3283
	// Called after deconfiguration. Cancels transfers on all endpoints.
sl@0
  3284
	ResetInterface(aErrorCode);
sl@0
  3285
	// Cancel the endpoint status notify request if it is outstanding.
sl@0
  3286
	const TInt KEpNotReq = RDevUsbcScClient::ERequestEndpointStatusNotify;
sl@0
  3287
	if (iRequestStatus[KEpNotReq])
sl@0
  3288
		{
sl@0
  3289
		CancelNotifyEndpointStatus();
sl@0
  3290
		Kern::RequestComplete(iClient, iRequestStatus[KEpNotReq], aErrorCode);
sl@0
  3291
		}
sl@0
  3292
	// We have to reset the alternate setting number when the config goes away.
sl@0
  3293
 	SelectAlternateSetting(0);
sl@0
  3294
	iAlternateSetting = 0;
sl@0
  3295
	}
sl@0
  3296
sl@0
  3297
sl@0
  3298
void DLddUsbcScChannel::StartEpReads()
sl@0
  3299
	{
sl@0
  3300
	// Queued after enumeration. Starts reads on all endpoints.
sl@0
  3301
	// The endpoint itself decides if it can do a read
sl@0
  3302
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 1"));
sl@0
  3303
	
sl@0
  3304
	TInt i;
sl@0
  3305
	TInt8 needsPacket;
sl@0
  3306
sl@0
  3307
	for (i=0; i<iNumBuffers; i++)
sl@0
  3308
		{
sl@0
  3309
		__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 2 %d",i));
sl@0
  3310
sl@0
  3311
		needsPacket = iBuffers[i].iNeedsPacket;
sl@0
  3312
		if (needsPacket)
sl@0
  3313
			{
sl@0
  3314
			__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 3"));
sl@0
  3315
			iBuffers[i].UpdateBufferList(0,0,(needsPacket==TUsbcScBuffer::KEpIsStarting));
sl@0
  3316
			}
sl@0
  3317
		}
sl@0
  3318
sl@0
  3319
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 4"));
sl@0
  3320
sl@0
  3321
		// now update ep0
sl@0
  3322
		iBuffers[iEP0OutBuff].Ep0CancelLddRead();
sl@0
  3323
		iBuffers[iEP0OutBuff].UpdateBufferList(0,0);
sl@0
  3324
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::StartEpReads - 5"));
sl@0
  3325
sl@0
  3326
	}
sl@0
  3327
sl@0
  3328
sl@0
  3329
void DLddUsbcScChannel::ResetInterface(TInt aErrorCode)
sl@0
  3330
	{
sl@0
  3331
	if (!iValidInterface && !iOwnsDeviceControl)
sl@0
  3332
			return;
sl@0
  3333
		
sl@0
  3334
	TInt i;
sl@0
  3335
	for (i=0; i<iNumBuffers; i++)
sl@0
  3336
		{
sl@0
  3337
		iBuffers[i].iNeedsPacket=TUsbcScBuffer::KNoEpAssigned;
sl@0
  3338
		}
sl@0
  3339
sl@0
  3340
	TUsbcScBuffer* buffer;
sl@0
  3341
sl@0
  3342
	for (i = 1; i <= iNumberOfEndpoints; i++)
sl@0
  3343
		{
sl@0
  3344
		// Firstly, cancel ('garbge collect') any stale reads/writes into PIL.
sl@0
  3345
sl@0
  3346
		__KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
sl@0
  3347
		iEndpoint[i]->AbortTransfer();
sl@0
  3348
sl@0
  3349
		// All OUT endpoints need a packet sent, to indicate the termination of the current ep 'pipe'.
sl@0
  3350
		// This will complete any current read, or will be read later.
sl@0
  3351
		// All IN endpoints must be simply cancelled, including anything queued.
sl@0
  3352
		// Ep0 operates outside alt settings, and so we don't cancel anything.
sl@0
  3353
sl@0
  3354
		buffer=iEndpoint[i]->GetBuffer();
sl@0
  3355
		if (buffer->iDirection==KUsbcScIn)
sl@0
  3356
			{
sl@0
  3357
			buffer->iStatusList.Complete(KErrCancel);	//aErrorCode 
sl@0
  3358
			buffer->iStatusList.CancelQueued();			//aErrorCode
sl@0
  3359
			}
sl@0
  3360
		else
sl@0
  3361
			buffer->iNeedsPacket=TUsbcScBuffer::KEpIsEnding;	// We will send a packet on re-start, which doubles as a 'cancel'
sl@0
  3362
															 	// for the old alt setting.
sl@0
  3363
		}
sl@0
  3364
	}
sl@0
  3365
sl@0
  3366
sl@0
  3367
sl@0
  3368
void DLddUsbcScChannel::EmergencyCompleteDfc(TAny* aDLddUsbcScChannel)
sl@0
  3369
	{
sl@0
  3370
	((DLddUsbcScChannel*) aDLddUsbcScChannel)->DoEmergencyComplete();
sl@0
  3371
	}
sl@0
  3372
sl@0
  3373
TInt DLddUsbcScChannel::DoEmergencyComplete()
sl@0
  3374
	{
sl@0
  3375
	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::DoEmergencyComplete"));
sl@0
  3376
	// cancel any pending DFCs
sl@0
  3377
	// complete all client requests
sl@0
  3378
sl@0
  3379
	TUsbcScBuffer* buffer;
sl@0
  3380
	TInt i;	
sl@0
  3381
	// Complete EP0 request
sl@0
  3382
sl@0
  3383
	TInt direction=iEp0Endpoint->iRequestCallbackInfo->iTransferDir;
sl@0
  3384
	if (direction==EControllerWrite)
sl@0
  3385
		{
sl@0
  3386
		iBuffers[iEP0InBuff].iStatusList.CancelQueued();
sl@0
  3387
		iBuffers[iEP0InBuff].iStatusList.Complete(KErrDisconnected);
sl@0
  3388
		}
sl@0
  3389
	else if (direction==EControllerRead)
sl@0
  3390
		{
sl@0
  3391
		iBuffers[iEP0OutBuff].iStatusList.CancelQueued();
sl@0
  3392
		iBuffers[iEP0OutBuff].iStatusList.Complete(KErrDisconnected);
sl@0
  3393
		}
sl@0
  3394
		
sl@0
  3395
	// Complete other Eps request
sl@0
  3396
	for (i = 1; i <= iNumberOfEndpoints; i++)
sl@0
  3397
		{
sl@0
  3398
		__KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
sl@0
  3399
		buffer=iEndpoint[i]->GetBuffer();
sl@0
  3400
		buffer->iStatusList.CancelQueued();
sl@0
  3401
		buffer->iStatusList.Complete(KErrDisconnected);
sl@0
  3402
		}
sl@0
  3403
sl@0
  3404
	// Complete remaining requests
sl@0
  3405
sl@0
  3406
    for (TInt i = 0; i < KUsbcMaxRequests; i++)
sl@0
  3407
        {
sl@0
  3408
        if (iRequestStatus[i])
sl@0
  3409
            {
sl@0
  3410
            __KTRACE_OPT(KUSB, Kern::Printf("Complete request 0x%x", iRequestStatus[i]));
sl@0
  3411
            Kern::RequestComplete(iClient, iRequestStatus[i], KErrDisconnected);
sl@0
  3412
            }
sl@0
  3413
        }
sl@0
  3414
    iStatusCallbackInfo.Cancel();
sl@0
  3415
    iEndpointStatusCallbackInfo.Cancel();
sl@0
  3416
    iOtgFeatureCallbackInfo.Cancel();
sl@0
  3417
sl@0
  3418
	return KErrNone;
sl@0
  3419
	}
sl@0
  3420
sl@0
  3421
sl@0
  3422
void DLddUsbcScChannel::PanicClientThread(TInt aReason)
sl@0
  3423
	{
sl@0
  3424
	Kern::ThreadKill(iClient, EExitPanic, aReason, KUsbLDDKillCat);
sl@0
  3425
	}
sl@0
  3426
sl@0
  3427
// End DLddUsbcScChannel
sl@0
  3428
sl@0
  3429
/*****************************************************************************\
sl@0
  3430
*    TUsbcScEndpoint                                                          *
sl@0
  3431
*                                                                             *
sl@0
  3432
*                                                                             *
sl@0
  3433
*                                                                             *
sl@0
  3434
\*****************************************************************************/
sl@0
  3435
sl@0
  3436
sl@0
  3437
// Constructor
sl@0
  3438
TUsbcScEndpoint::TUsbcScEndpoint(DLddUsbcScChannel* aLDD, DUsbClientController* aController,
sl@0
  3439
							 const TUsbcScEndpointInfo* aEndpointInfo, TInt aEndpointNum
sl@0
  3440
							 )
sl@0
  3441
	: iRequestCallbackInfo(NULL),
sl@0
  3442
	  iController(aController),
sl@0
  3443
	  iEndpointInfo(*aEndpointInfo),
sl@0
  3444
	  iClientReadPending(EFalse),
sl@0
  3445
	  iClientWritePending(EFalse),
sl@0
  3446
	  iEndpointNumber(aEndpointNum),
sl@0
  3447
	  iRealEpNumber(-1),
sl@0
  3448
	  iLdd(aLDD),
sl@0
  3449
	  iError(KErrNone),
sl@0
  3450
	  iBytesTransferred(0),
sl@0
  3451
	  iBuffer(NULL)
sl@0
  3452
	{
sl@0
  3453
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::TUsbcScEndpoint"));
sl@0
  3454
	}
sl@0
  3455
sl@0
  3456
sl@0
  3457
TInt TUsbcScEndpoint::Construct()
sl@0
  3458
	{
sl@0
  3459
	__KTRACE_OPT(KUSB,Kern::Printf("TUsbcScEndpoint::TUsbcScEndpoint iEndpointNumber %d\n",iEndpointNumber));
sl@0
  3460
sl@0
  3461
	iRequestCallbackInfo = new TUsbcRequestCallback(iLdd,
sl@0
  3462
													iEndpointNumber,
sl@0
  3463
													(iEndpointNumber==0)?DLddUsbcScChannel::RequestCallbackEp0:TUsbcScEndpoint::RequestCallback,
sl@0
  3464
													(iEndpointNumber==0)?  (TAny*) iLdd:  (TAny*) this,
sl@0
  3465
													iLdd->iDfcQ,
sl@0
  3466
													KUsbRequestCallbackPriority);
sl@0
  3467
sl@0
  3468
	return (iRequestCallbackInfo == NULL)?KErrNoMemory:KErrNone;
sl@0
  3469
	}
sl@0
  3470
sl@0
  3471
sl@0
  3472
TUsbcScEndpoint::~TUsbcScEndpoint()
sl@0
  3473
	{
sl@0
  3474
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::~TUsbcScEndpoint(%d)", iEndpointNumber));
sl@0
  3475
	AbortTransfer();
sl@0
  3476
	delete iRequestCallbackInfo;
sl@0
  3477
	}
sl@0
  3478
sl@0
  3479
// This is called by the PIL, on return from a read or write.
sl@0
  3480
// Inturn it calls either the read or write function for that buffer.
sl@0
  3481
sl@0
  3482
void TUsbcScEndpoint::RequestCallback(TAny* aTUsbcScEndpoint)
sl@0
  3483
	{
sl@0
  3484
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::RequestCallback"));
sl@0
  3485
sl@0
  3486
	if (((TUsbcScEndpoint*)aTUsbcScEndpoint)->iLdd->ChannelClosing())
sl@0
  3487
		{
sl@0
  3488
		__KTRACE_OPT(KUSB, Kern::Printf("Channel Closing: Completion not accepted!"));
sl@0
  3489
		return;
sl@0
  3490
		}
sl@0
  3491
sl@0
  3492
	switch (((TUsbcScEndpoint*) aTUsbcScEndpoint)->iRequestCallbackInfo->iTransferDir)
sl@0
  3493
	{
sl@0
  3494
	case EControllerWrite:
sl@0
  3495
		((TUsbcScEndpoint*) aTUsbcScEndpoint)->iBuffer->CompleteWrite();
sl@0
  3496
		return;
sl@0
  3497
	case EControllerRead:
sl@0
  3498
		((TUsbcScEndpoint*) aTUsbcScEndpoint)->iBuffer->CompleteRead();
sl@0
  3499
		return;
sl@0
  3500
	default:
sl@0
  3501
		Kern::Printf("TUsbcScEndpoint::RequestCallback - Unexpected compleation direction %d",((TUsbcScEndpoint*) aTUsbcScEndpoint)->iRequestCallbackInfo->iTransferDir);
sl@0
  3502
		Kern::Fault("TUsbcScEndpoint::RequestCallback", __LINE__);
sl@0
  3503
	} 
sl@0
  3504
	}
sl@0
  3505
sl@0
  3506
sl@0
  3507
/*
sl@0
  3508
sl@0
  3509
This is used to tidy up cancel calls into the PIL, regardless of them being reads or writes
sl@0
  3510
sl@0
  3511
*/
sl@0
  3512
sl@0
  3513
void TUsbcScEndpoint::AbortTransfer()
sl@0
  3514
	{
sl@0
  3515
	if (!iLdd->iRealizeCalled)
sl@0
  3516
		{
sl@0
  3517
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::AbortTransfer Ep# %d Real Ep # %d - N.R.",iEndpointNumber, iRealEpNumber));
sl@0
  3518
		return;
sl@0
  3519
		} 
sl@0
  3520
	else
sl@0
  3521
		{
sl@0
  3522
		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint::AbortTransfer Ep# %d Real Ep # %d",iEndpointNumber, iRealEpNumber));
sl@0
  3523
		}
sl@0
  3524
sl@0
  3525
	
sl@0
  3526
	if (iBuffer && (iBuffer->iStatusList.iState) || (!iRealEpNumber))
sl@0
  3527
		{
sl@0
  3528
		if (iRequestCallbackInfo->iTransferDir==EControllerWrite)
sl@0
  3529
			iController->CancelWriteBuffer(iLdd, iRealEpNumber);
sl@0
  3530
		else if (iRequestCallbackInfo->iTransferDir==EControllerRead)
sl@0
  3531
			iController->CancelReadBuffer(iLdd, iRealEpNumber);
sl@0
  3532
		else
sl@0
  3533
			{
sl@0
  3534
			if (iEndpointNumber!=0) // endpoint zero starts off not sent in any direction, then keeps changing.
sl@0
  3535
				{
sl@0
  3536
				__KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: Invalid Direction %d on (%d,%d)!\n",iRequestCallbackInfo->iTransferDir,iEndpointNumber, iRealEpNumber));
sl@0
  3537
				}
sl@0
  3538
			else
sl@0
  3539
				{
sl@0
  3540
				__KTRACE_OPT(KUSB, Kern::Printf("\nTUsbcScEndpoint::AbortTransfer Can't stop direction %d on (%d,%d)!\n",iRequestCallbackInfo->iTransferDir,iEndpointNumber, iRealEpNumber));
sl@0
  3541
				}
sl@0
  3542
			}
sl@0
  3543
		}
sl@0
  3544
	else if (!iBuffer)
sl@0
  3545
		{
sl@0
  3546
		__KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: iBuffer is NULL on (%d,%d)\n",iEndpointNumber, iRealEpNumber));
sl@0
  3547
		return;
sl@0
  3548
		}
sl@0
  3549
	
sl@0
  3550
	if (iRequestCallbackInfo)
sl@0
  3551
		iRequestCallbackInfo->iDfc.Cancel();
sl@0
  3552
	else
sl@0
  3553
		{
sl@0
  3554
		__KTRACE_OPT(KUSB,Kern::Printf("\nTUsbcScEndpoint::AbortTransfer WARNING: iRequestCallbackInfo is NULL\n"));
sl@0
  3555
		}
sl@0
  3556
		
sl@0
  3557
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScEndpoint Done."));
sl@0
  3558
	}
sl@0
  3559
sl@0
  3560
// End TUsbcScEndpoint
sl@0
  3561
sl@0
  3562
sl@0
  3563
/*****************************************************************************\
sl@0
  3564
*    TUsbcScAlternateSettingList                                              *
sl@0
  3565
*                                                                             *
sl@0
  3566
*                                                                             *
sl@0
  3567
*                                                                             *
sl@0
  3568
\*****************************************************************************/
sl@0
  3569
sl@0
  3570
sl@0
  3571
TUsbcScAlternateSetting::TUsbcScAlternateSetting()
sl@0
  3572
	: iNext(NULL),
sl@0
  3573
	  iPrevious(NULL),
sl@0
  3574
	  iNumberOfEndpoints(0),
sl@0
  3575
	  iSetting(0)
sl@0
  3576
	{
sl@0
  3577
	for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
sl@0
  3578
		{
sl@0
  3579
		iEndpoint[i] = NULL;
sl@0
  3580
		}
sl@0
  3581
	}
sl@0
  3582
sl@0
  3583
sl@0
  3584
TUsbcScAlternateSetting::~TUsbcScAlternateSetting()
sl@0
  3585
	{
sl@0
  3586
	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcScAlternateSetting::~TUsbcScAlternateSetting()"));
sl@0
  3587
	for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
sl@0
  3588
		{
sl@0
  3589
		delete iEndpoint[i];
sl@0
  3590
		}
sl@0
  3591
	}
sl@0
  3592
sl@0
  3593
// End TUsbcScAlternateSettingList
sl@0
  3594
sl@0
  3595
sl@0
  3596
sl@0
  3597
TUsbcScAlternateSettingList::TUsbcScAlternateSettingList()
sl@0
  3598
	: iHead(NULL),
sl@0
  3599
	  iTail(NULL)
sl@0
  3600
	{
sl@0
  3601
	}
sl@0
  3602
sl@0
  3603
TUsbcScAlternateSettingList::~TUsbcScAlternateSettingList()
sl@0
  3604
	{
sl@0
  3605
	}
sl@0
  3606
sl@0
  3607
sl@0
  3608
sl@0
  3609
/*****************************************************************************\
sl@0
  3610
*   TUsbcDeviceStatusQueue                                                    *
sl@0
  3611
*                                                                             *
sl@0
  3612
*                                                                             *
sl@0
  3613
*                                                                             *
sl@0
  3614
\*****************************************************************************/
sl@0
  3615
sl@0
  3616
sl@0
  3617
TUsbcDeviceStatusQueue::TUsbcDeviceStatusQueue()
sl@0
  3618
	{
sl@0
  3619
	FlushQueue();
sl@0
  3620
	}
sl@0
  3621
sl@0
  3622
sl@0
  3623
void TUsbcDeviceStatusQueue::FlushQueue()
sl@0
  3624
	{
sl@0
  3625
	for (TInt i = 0; i < KUsbDeviceStatusQueueDepth; i++)
sl@0
  3626
		{
sl@0
  3627
		iDeviceStatusQueue[i] = KUsbDeviceStatusNull;
sl@0
  3628
		}
sl@0
  3629
	iStatusQueueHead = 0;
sl@0
  3630
	}
sl@0
  3631
sl@0
  3632
sl@0
  3633
void TUsbcDeviceStatusQueue::AddStatusToQueue(TUint32 aDeviceStatus)
sl@0
  3634
	{
sl@0
  3635
	// Only add a new status if it is not a duplicate of the one at the head of the queue
sl@0
  3636
	if (!(iStatusQueueHead != 0 &&
sl@0
  3637
		  iDeviceStatusQueue[iStatusQueueHead - 1] == aDeviceStatus))
sl@0
  3638
		{
sl@0
  3639
		if (iStatusQueueHead == KUsbDeviceStatusQueueDepth)
sl@0
  3640
			{
sl@0
  3641
			// Discard item at tail of queue
sl@0
  3642
			TUint32 status;
sl@0
  3643
			GetDeviceQueuedStatus(status);
sl@0
  3644
			}
sl@0
  3645
		iDeviceStatusQueue[iStatusQueueHead] = aDeviceStatus;
sl@0
  3646
		iStatusQueueHead++;
sl@0
  3647
		}
sl@0
  3648
	}
sl@0
  3649
sl@0
  3650
sl@0
  3651
TInt TUsbcDeviceStatusQueue::GetDeviceQueuedStatus(TUint32& aDeviceStatus)
sl@0
  3652
	{
sl@0
  3653
	TInt r = KErrNone;
sl@0
  3654
	if (iStatusQueueHead <= 0)
sl@0
  3655
		{
sl@0
  3656
		r = KErrGeneral;
sl@0
  3657
		aDeviceStatus = KUsbDeviceStatusNull;
sl@0
  3658
		}
sl@0
  3659
	else
sl@0
  3660
		{
sl@0
  3661
		aDeviceStatus = iDeviceStatusQueue[0];
sl@0
  3662
		for(TInt i = 1; i < KUsbDeviceStatusQueueDepth; i++)
sl@0
  3663
			{
sl@0
  3664
			TUint32 s = iDeviceStatusQueue[i];
sl@0
  3665
			iDeviceStatusQueue[i - 1] = s;
sl@0
  3666
			}
sl@0
  3667
		iStatusQueueHead--;
sl@0
  3668
		iDeviceStatusQueue[KUsbDeviceStatusQueueDepth - 1] = KUsbDeviceStatusNull;
sl@0
  3669
		}
sl@0
  3670
	return r;
sl@0
  3671
	}
sl@0
  3672
sl@0
  3673
// End TUsbcDeviceStatusQueue
sl@0
  3674
sl@0
  3675
//---
sl@0
  3676