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