kernel/eka/drivers/usbc/d_usbc.cpp
changeset 0 a41df078684a
child 6 0173bcd7697c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/usbc/d_usbc.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,3058 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/drivers/usbc/d_usbc.cpp
+// LDD for USB Device driver stack:
+// The channel object.
+// 
+//
+
+/**
+ @file d_usbc.cpp
+ @internalTechnology
+*/
+
+#include <drivers/usbc.h>
+
+
+_LIT(KUsbLddName, "Usbc");
+
+static const TInt KUsbRequestCallbackPriority = 2;
+
+
+// Quick sanity check on endpoint properties
+static TBool ValidateEndpoint(const TUsbcEndpointInfo* aEndpointInfo)
+	{
+	const TUint dir = aEndpointInfo->iDir;
+	const TInt size = aEndpointInfo->iSize;
+	if (size <= 0)
+		return EFalse;
+
+	switch (aEndpointInfo->iType)
+		{
+	case KUsbEpTypeControl:
+		if (dir != KUsbEpDirBidirect || size > 64)
+			return EFalse;
+		break;
+	case KUsbEpTypeIsochronous:
+		if ((dir != KUsbEpDirIn && dir != KUsbEpDirOut) || size > 1024)
+			return EFalse;
+		break;
+	case KUsbEpTypeBulk:
+		if ((dir != KUsbEpDirIn && dir != KUsbEpDirOut) || size > 512)
+			return EFalse;
+		break;
+	case KUsbEpTypeInterrupt:
+		if ((dir != KUsbEpDirIn && dir != KUsbEpDirOut) || size > 1024)
+			return EFalse;
+		break;
+	default:
+		return EFalse;
+		}
+	return ETrue;
+	}
+
+
+/** Real entry point from the Kernel: return a new driver.
+ */
+DECLARE_STANDARD_LDD()
+	{
+	return new DUsbcLogDevice;
+	}
+
+
+/** Create a channel on the device.
+
+	@internalComponent
+*/
+TInt DUsbcLogDevice::Create(DLogicalChannelBase*& aChannel)
+	{
+	aChannel = new DLddUsbcChannel;
+	return aChannel ? KErrNone : KErrNoMemory;
+	}
+
+
+DUsbcLogDevice::DUsbcLogDevice()
+      {
+	  iParseMask = KDeviceAllowUnit;
+	  iUnitsMask = 0xffffffff;								// Leave units decision to the Controller
+      iVersion = TVersion(KUsbcMajorVersion, KUsbcMinorVersion, KUsbcBuildVersion);
+      }
+
+
+TInt DUsbcLogDevice::Install()
+	{
+	// Only proceed if we have the Controller underneath us
+	if (!DUsbClientController::UsbcControllerPointer())
+		{
+		__KTRACE_OPT(KPANIC, Kern::Printf("LDD Install: USB Controller Not Present"));
+		return KErrGeneral;
+		}
+	return SetName(&KUsbLddName);
+	}
+
+
+//
+// Return the USB controller capabilities.
+//
+void DUsbcLogDevice::GetCaps(TDes8& aDes) const
+	{
+	TPckgBuf<TCapsDevUsbc> b;
+	b().version = iVersion;
+	Kern::InfoCopy(aDes, b);
+	}
+
+
+//
+// Constructor
+//
+DLddUsbcChannel::DLddUsbcChannel()
+	: iValidInterface(EFalse),
+	  iAlternateSettingList(NULL),
+	  iCompleteAllCallbackInfo(this, DLddUsbcChannel::EmergencyCompleteDfc, KUsbRequestCallbackPriority),
+	  iStatusChangePtr(NULL),
+	  iStatusCallbackInfo(this, DLddUsbcChannel::StatusChangeCallback, KUsbRequestCallbackPriority),
+	  iEndpointStatusChangePtr(NULL),
+	  iEndpointStatusCallbackInfo(this, DLddUsbcChannel::EndpointStatusChangeCallback,
+								  KUsbRequestCallbackPriority),
+      iOtgFeatureChangePtr(NULL),
+      iOtgFeatureCallbackInfo(this, DLddUsbcChannel::OtgFeatureChangeCallback, KUsbRequestCallbackPriority),
+	  iBufferBaseEp0(NULL),
+	  iBufferSizeEp0(0),
+	  iNumberOfEndpoints(0),
+	  iHwChunkIN(NULL),
+	  iHwChunkOUT(NULL),
+	  iHwChunkEp0(NULL),
+	  iDeviceState(EUsbcDeviceStateUndefined),
+	  iOwnsDeviceControl(EFalse),
+	  iAlternateSetting(0),
+	  iDeviceStatusNeeded(EFalse),
+	  iChannelClosing(EFalse)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("*** DLddUsbcChannel::DLddUsbcChannel CTOR"));
+	iClient = &Kern::CurrentThread();
+	iClient->Open();
+	for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
+		{
+		iEndpoint[i] = NULL;
+		}
+	for (TInt i = 1; i < KUsbcMaxRequests; i++)
+		{
+		iRequestStatus[i] = NULL;
+		}
+	}
+
+
+DLddUsbcChannel::~DLddUsbcChannel()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcChannel::~DLddUsbcChannel()"));
+	if (iController)
+		{
+		iStatusCallbackInfo.Cancel();
+		iEndpointStatusCallbackInfo.Cancel();
+        iOtgFeatureCallbackInfo.Cancel();
+        iCompleteAllCallbackInfo.Cancel();
+		AbortInterface();
+		DestroyAllInterfaces();
+		if (iOwnsDeviceControl)
+			{
+			iController->ReleaseDeviceControl(this);
+			iOwnsDeviceControl = EFalse;
+			}
+		iController->DeRegisterClient(this);
+		DestroyEp0();
+		delete iStatusFifo;
+		Kern::DestroyClientRequest(iStatusChangeReq);
+		Kern::DestroyClientRequest(iEndpointStatusChangeReq);
+		Kern::DestroyClientRequest(iOtgFeatureChangeReq);
+
+		Kern::DestroyVirtualPinObject(iPinObj1);
+		Kern::DestroyVirtualPinObject(iPinObj2);
+		Kern::DestroyVirtualPinObject(iPinObj3);
+
+		for (TInt i = 0; i < KUsbcMaxRequests; i++)
+			{
+			Kern::DestroyClientBufferRequest(iClientAsynchNotify[i]->iBufferRequest);
+			delete iClientAsynchNotify[i];
+			}
+		}
+	Kern::SafeClose((DObject*&)iClient, NULL);
+	}
+
+
+inline TBool DLddUsbcChannel::ValidEndpoint(TInt aEndpoint)
+	{
+	return (aEndpoint <= iNumberOfEndpoints && aEndpoint >= 0);
+	}
+
+
+//
+// Create channel
+//
+TInt DLddUsbcChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("LDD DoCreateL 1 Ver = %02d %02d %02d",
+									aVer.iMajor, aVer.iMinor, aVer.iBuild));
+	if (!Kern::CurrentThreadHasCapability(ECapabilityCommDD,
+										  __PLATSEC_DIAGNOSTIC_STRING("Checked by USBC.LDD (USB Driver)")))
+		{
+		return KErrPermissionDenied;
+		}
+
+	iController = DUsbClientController::UsbcControllerPointer();
+
+	if (!iController)
+		{
+		return KErrGeneral;
+		}
+
+	iStatusFifo = new TUsbcDeviceStatusQueue;
+	if (iStatusFifo == NULL)
+		{
+		return KErrNoMemory;
+		}
+
+  	if (!Kern::QueryVersionSupported(TVersion(KUsbcMajorVersion, KUsbcMinorVersion, KUsbcBuildVersion), aVer))
+		{
+		return KErrNotSupported;
+		}
+
+	// set up the correct DFC queue
+	SetDfcQ(iController->DfcQ(0));							// sets the channel's dfc queue
+	#ifdef DFC_REALTIME_STATE
+		iDfcQ.SetRealtimeState(ERealtimeStateOn);
+	#endif
+    iCompleteAllCallbackInfo.SetDfcQ(iDfcQ);
+	iStatusCallbackInfo.SetDfcQ(iDfcQ);						// use the channel's dfcq for this dfc
+	iEndpointStatusCallbackInfo.SetDfcQ(iDfcQ);				// use the channel's dfcq for this dfc
+    iOtgFeatureCallbackInfo.SetDfcQ(iDfcQ);
+	iMsgQ.Receive();										//start up the message q
+	TInt r = iController->RegisterClientCallback(iCompleteAllCallbackInfo);
+	if (r != KErrNone)
+		return r;
+	r = iController->RegisterForStatusChange(iStatusCallbackInfo);
+	if (r != KErrNone)
+		return r;
+	r = iController->RegisterForEndpointStatusChange(iEndpointStatusCallbackInfo);
+	if (r != KErrNone)
+		return r;
+	r = iController->RegisterForOtgFeatureChange(iOtgFeatureCallbackInfo);
+	if (r != KErrNone)
+		return r;
+
+	r = Kern::CreateClientDataRequest(iStatusChangeReq);
+	if (r != KErrNone)
+		return r;
+	r = Kern::CreateClientDataRequest(iEndpointStatusChangeReq);
+	if (r != KErrNone)
+		return r;
+	r = Kern::CreateClientDataRequest(iOtgFeatureChangeReq);
+	if (r != KErrNone)
+		return r;
+	
+	Kern::CreateVirtualPinObject(iPinObj1);
+	Kern::CreateVirtualPinObject(iPinObj2);
+	Kern::CreateVirtualPinObject(iPinObj3);
+
+	for (TInt i = 0; i < KUsbcMaxRequests; i++)
+		{
+			iClientAsynchNotify[i] = new TClientAsynchNotify;
+			if(iClientAsynchNotify[i] == NULL)
+				return KErrNoMemory;
+			r = Kern::CreateClientBufferRequest(iClientAsynchNotify[i]->iBufferRequest,1,TClientBufferRequest::EPinVirtual);
+			if (r != KErrNone)
+				{
+				delete iClientAsynchNotify[i];
+				iClientAsynchNotify[i]=NULL;
+				return r;
+				}
+		}
+	
+	return r;
+	}
+
+
+
+void DLddUsbcChannel::CompleteBufferRequest(DThread* aThread, TInt aReqNo, TInt aReason)
+{
+	iRequestStatus[aReqNo]=NULL;
+	Kern::QueueBufferRequestComplete(aThread, iClientAsynchNotify[aReqNo]->iBufferRequest, aReason);
+}
+
+
+TClientBuffer * DLddUsbcChannel::GetClientBuffer(TInt aEndpoint)
+{
+	return iClientAsynchNotify[aEndpoint]->iClientBuffer;
+}
+
+//Runs in client thread
+TInt DLddUsbcChannel::SendMsg(TMessageBase * aMsg)
+{
+	TThreadMessage& m=* (TThreadMessage*)aMsg;
+	TInt id = m.iValue;
+	
+	TInt r = KErrNone;
+	//Cancel Request
+	if (id == KMaxTInt)
+		{
+			r = DLogicalChannel::SendMsg(aMsg);
+			return r;
+		}
+	if (id < 0)
+		{
+		// DoRequest
+		TRequestStatus* pS = (TRequestStatus*) m.Ptr0();
+		r = PreSendRequest(aMsg,~id, pS, m.Ptr1(), m.Ptr2());
+		if (r == KErrNone)
+			{
+			r = DLogicalChannel::SendMsg(aMsg);
+			}
+		}
+	else
+		{
+		//SendControl
+		r = SendControl(aMsg);
+		}
+	return r;
+}
+
+
+TInt DLddUsbcChannel::PreSendRequest(TMessageBase * aMsg,TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+{
+	TInt r = KErrNone;
+	if (aReqNo >= KUsbcMaxRequests)
+	{
+		Kern::RequestComplete(aStatus, KErrNotSupported);
+		return KErrNotSupported;
+	}
+	if (aReqNo > KUsbcMaxEpNumber)//DoOtherAsyncReq
+	{
+		switch (aReqNo)
+		{
+			case RDevUsbcClient::ERequestEndpointStatusNotify:
+				iEndpointStatusChangeReq->Reset();
+				iEndpointStatusChangeReq->SetStatus(aStatus);
+				iEndpointStatusChangeReq->SetDestPtr(a1);
+			break;
+			case RDevUsbcClient::ERequestOtgFeaturesNotify:
+				iOtgFeatureChangeReq->Reset();
+				iOtgFeatureChangeReq->SetStatus(aStatus);
+				iOtgFeatureChangeReq->SetDestPtr(a1);
+			break;
+			case RDevUsbcClient::ERequestAlternateDeviceStatusNotify:
+				iStatusChangeReq->Reset();
+				iStatusChangeReq->SetStatus(aStatus);
+				iStatusChangeReq->SetDestPtr(a1);
+			break;
+			case RDevUsbcClient::ERequestReEnumerate://WE use bufferrequest to complete even tho we dont add any buffers
+				iClientAsynchNotify[aReqNo]->Reset();
+				r=iClientAsynchNotify[aReqNo]->iBufferRequest->StartSetup(aStatus);
+				if (r != KErrNone)
+					return r;
+				iClientAsynchNotify[aReqNo]->iBufferRequest->EndSetup();
+			break;
+		}
+	}
+	else //DoTransferAsyncReq
+	{
+			if(a1 == NULL)
+				return KErrArgument;
+			iClientAsynchNotify[aReqNo]->Reset();
+			r=iClientAsynchNotify[aReqNo]->iBufferRequest->StartSetup(aStatus);
+			if (r != KErrNone)
+				return r;
+			kumemget(&iTfrInfo,a1,sizeof(TEndpointTransferInfo));
+			r=iClientAsynchNotify[aReqNo]->iBufferRequest->AddBuffer(iClientAsynchNotify[aReqNo]->iClientBuffer, iTfrInfo.iDes);
+			if (r != KErrNone)
+				return r;
+			iClientAsynchNotify[aReqNo]->iBufferRequest->EndSetup();
+			TThreadMessage& m=*(TThreadMessage*)aMsg;
+			m.iArg[1] = (TAny*)&iTfrInfo; //Use Channel owned TransfereInfo structure 
+	}
+	return KErrNone;
+}
+
+
+void DLddUsbcChannel::HandleMsg(TMessageBase* aMsg)
+	{
+	TThreadMessage& m = *(TThreadMessage*)aMsg;
+	TInt id = m.iValue;
+	if (id == (TInt) ECloseMsg)
+		{
+		iChannelClosing = ETrue;
+		m.Complete(KErrNone, EFalse);
+		return;
+		}
+	else if (id == KMaxTInt)
+		{
+		// Cancel request
+		TInt mask = m.Int0();
+		TInt b = 1;
+		for(TInt reqNo = 0; reqNo < KUsbcMaxRequests; reqNo++)
+			{
+			TRequestStatus* pS = iRequestStatus[reqNo];
+			if ((mask & b) && (pS != NULL))
+				{
+				DoCancel(reqNo);
+				}
+			b <<= 1;
+			}
+		m.Complete(KErrNone, ETrue);
+		return;
+		}
+
+	if (id < 0)
+		{
+		// DoRequest
+		TRequestStatus* pS = (TRequestStatus*) m.Ptr0();
+		DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
+		m.Complete(KErrNone, ETrue);
+		}
+	else
+		{
+		// DoControl
+		TInt r = DoControl(id, m.Ptr0(), m.Ptr1());
+		m.Complete(r, ETrue);
+		}
+	}
+
+
+//
+// Overriding DObject virtual
+//
+TInt DLddUsbcChannel::RequestUserHandle(DThread* aThread, TOwnerType /*aType*/)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcChannel::RequestUserHandle"));
+	// The USB client LDD is not designed for a channel to be shared between
+	// threads. It saves a pointer to the current thread when it is opened, and
+	// uses this to complete any asynchronous requests.
+	// It is therefore not acceptable for the handle to be duplicated and used
+	// by another thread:
+	if (aThread == iClient)
+		{
+		return KErrNone;
+		}
+	else
+		{
+		return KErrAccessDenied;
+		}
+	}
+
+
+//
+// Asynchronous requests - overriding pure virtual
+//
+void DLddUsbcChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+	{
+	// Check on request status
+	__KTRACE_OPT(KUSB, Kern::Printf("DoRequest 0x%08x", aReqNo));
+		TInt r = KErrNone;
+		if (iRequestStatus[aReqNo] != NULL)
+			{
+			DestroyAllInterfaces();
+			PanicClientThread(ERequestAlreadyPending);
+			}
+		else
+			{
+			TBool needsCompletion;
+			iRequestStatus[aReqNo] = aStatus;
+
+			if (aReqNo > KUsbcMaxEpNumber)
+				{
+				r = DoOtherAsyncReq(aReqNo, a1, a2, needsCompletion);
+				if (needsCompletion)
+					{
+					switch (aReqNo)
+					{
+						case RDevUsbcClient::ERequestEndpointStatusNotify:
+							iRequestStatus[aReqNo]=NULL;
+							Kern::QueueRequestComplete(iClient,iEndpointStatusChangeReq,r);
+						break;
+						case RDevUsbcClient::ERequestOtgFeaturesNotify:
+							iRequestStatus[aReqNo]=NULL;
+							Kern::QueueRequestComplete(iClient,iOtgFeatureChangeReq,r);
+						break;
+						case RDevUsbcClient::ERequestAlternateDeviceStatusNotify:
+							iRequestStatus[aReqNo]=NULL;
+							Kern::QueueRequestComplete(iClient,iStatusChangeReq,r);
+						break;
+						case RDevUsbcClient::ERequestReEnumerate:
+							iRequestStatus[aReqNo]=NULL;
+							Kern::QueueBufferRequestComplete(iClient, iClientAsynchNotify[aReqNo]->iBufferRequest, r);
+						break;
+					}
+				  }
+				}
+			else
+				{
+				r = DoTransferAsyncReq(aReqNo, a1, a2, needsCompletion);
+				if (needsCompletion)
+					{
+					//Kern::RequestComplete(iClient, iRequestStatus[aReqNo], r);
+					CompleteBufferRequest(iClient, aReqNo, r);
+					}
+				}
+			}
+	}
+
+
+
+TInt DLddUsbcChannel::DoOtherAsyncReq(TInt aReqNo, TAny* a1, TAny* a2, TBool& aNeedsCompletion)
+	{
+	// The general assumption is that none of these will complete now.
+	// However, those that make this function return something other than
+	// KErrNone will get completed by the calling function.
+	// So, 1) If you are returning KErrNone but really need to complete because
+	//        completion criteria can be met (for example, sufficient data is
+	//        available in the buffer) and then set aNeedsCompletion = ETrue.
+	//     2) Do NOT complete here AT ALL.
+	//
+	aNeedsCompletion = EFalse;
+	TInt r = KErrNone;
+
+	switch (aReqNo)
+		{
+	case RDevUsbcClient::ERequestAlternateDeviceStatusNotify:
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlReqDeviceStatusNotify"));
+		if (a1 != NULL)
+			{
+			iDeviceStatusNeeded = ETrue;
+			iStatusChangePtr = a1;
+			aNeedsCompletion = AlternateDeviceStateTestComplete();
+			}
+		else
+			r = KErrArgument;
+		break;
+		}
+	case RDevUsbcClient::ERequestReEnumerate:
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("ERequestReEnumerate"));
+		// If successful, this will complete via the status notification.
+		r = iController->ReEnumerate();
+		break;
+		}
+	case RDevUsbcClient::ERequestEndpointStatusNotify:
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("ERequestEndpointStatusNotify"));
+		if (a1 != NULL)
+			{
+			iEndpointStatusChangePtr = a1;
+			}
+		else
+			r = KErrArgument;
+		break;
+			}
+	case RDevUsbcClient::ERequestOtgFeaturesNotify:
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("ERequestOtgFeaturesNotify"));
+		if (a1 != NULL)
+			{
+            iOtgFeatureChangePtr = a1;
+            }
+		else
+			r = KErrArgument;
+        break;
+        }
+    default:
+		r = KErrNotSupported;
+		}
+
+	aNeedsCompletion = aNeedsCompletion || (r != KErrNone);
+
+	return r;
+	}
+
+
+TInt DLddUsbcChannel::DoTransferAsyncReq(TInt aEndpointNum, TAny* a1, TAny* a2, TBool& aNeedsCompletion)
+	{
+	// The general assumption is that none of these will complete now.
+	// however, those that are returning something other than KErrNone will get completed
+	// by the calling function.
+	// So,	1) if you are returning KErrNone but really need to complete because completion criteria can be met
+	//			(for example, sufficient data is available in the buffer) and then set aNeedsCompletion=ETrue..
+	//		2) Do NOT complete here AT ALL.
+	//
+	aNeedsCompletion = EFalse;
+	TInt r = KErrNone;
+	TUsbcEndpoint* pEndpoint = NULL;
+	TUsbcEndpointInfo* pEndpointInfo = NULL;
+	TEndpointTransferInfo* pTfr = NULL;
+
+	if (aEndpointNum == 0)
+		{
+		// ep0 requests
+		if (!(iValidInterface || iOwnsDeviceControl))
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("DoRequest rejected: not configured (Ep0)"));
+			r = KErrUsbInterfaceNotReady;
+			goto exit;
+			}
+		}
+	else
+		{
+		// other eps
+		if (!(iValidInterface && (iDeviceState == EUsbcDeviceStateConfigured ||
+		                          iDeviceState == EUsbcDeviceStateSuspended))
+		   )
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("DoRequest rejected not configured (Ep %d)", aEndpointNum));
+			r = KErrUsbInterfaceNotReady;
+			goto exit;
+			}
+		}
+
+	if (!ValidEndpoint(aEndpointNum))
+		{
+		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Read: in error complete"));
+		r = KErrUsbEpNotInInterface;
+		goto exit;
+ 		}
+
+	if (a1 == NULL)
+		{
+		r = KErrArgument;
+		goto exit;
+		}
+	pTfr = (TEndpointTransferInfo *)a1;
+
+	if (pTfr->iTransferSize < 0)
+		{
+		r = KErrArgument;
+		goto exit;
+		}
+	pEndpoint = iEndpoint[aEndpointNum];
+	if (!pEndpoint)
+		{
+		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Read: in error complete"));
+		r = KErrUsbEpNotInInterface;
+		goto exit;
+		}
+
+	pEndpointInfo = pEndpoint->EndpointInfo();
+	__KTRACE_OPT(KUSB, Kern::Printf("DoRequest %d", aEndpointNum));
+
+	switch (pTfr->iTransferType)
+		{
+
+	case ETransferTypeReadData:
+	case ETransferTypeReadPacket:
+	case ETransferTypeReadUntilShort:
+	case ETransferTypeReadOneOrMore:
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read"));
+		if (pEndpoint->iDmaBuffers->RxIsActive())
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("**** ReadReq ep%d RxActive", aEndpointNum));
+			}
+		else
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("**** ReadReq ep%d RxInActive", aEndpointNum));
+			}
+
+		if (pEndpointInfo->iDir != KUsbEpDirOut &&
+			pEndpointInfo->iDir != KUsbEpDirBidirect)
+			{
+			// Trying to do the wrong thing
+			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Read: in error complete"));
+			r = KErrUsbEpBadDirection;
+			break;
+			}
+		// Set the length of data to zero now to catch all cases
+		TPtrC8 pZeroDesc(NULL, 0);
+		r=Kern::ThreadBufWrite(iClient,iClientAsynchNotify[aEndpointNum]->iClientBuffer, pZeroDesc, 0, 0,iClient);
+		if (r != KErrNone)
+			PanicClientThread(r);
+		pEndpoint->SetTransferInfo(pTfr);
+		if (pEndpoint->iDmaBuffers->IsReaderEmpty())
+			{
+			pEndpoint->SetClientReadPending(ETrue);
+			}
+		else
+			{
+			if (pTfr->iTransferType == ETransferTypeReadPacket)
+				{
+				__KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read packet: data available complete"));
+				r = pEndpoint->CopyToClient(iClient,iClientAsynchNotify[aEndpointNum]->iClientBuffer);
+				aNeedsCompletion = ETrue;
+				break;
+				}
+			else if (pTfr->iTransferType == ETransferTypeReadData)
+				{
+				if (pTfr->iTransferSize <= pEndpoint->RxBytesAvailable())
+					{
+					__KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read data: data available complete"));
+					r = pEndpoint->CopyToClient(iClient,iClientAsynchNotify[aEndpointNum]->iClientBuffer);
+					aNeedsCompletion = ETrue;
+					break;
+					}
+				else
+					{
+					pEndpoint->SetClientReadPending(ETrue);
+					}
+				}
+			else if (pTfr->iTransferType == ETransferTypeReadOneOrMore)
+				{
+				if (pEndpoint->RxBytesAvailable() > 0)
+					{
+					__KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read data: data available complete"));
+					r = pEndpoint->CopyToClient(iClient,iClientAsynchNotify[aEndpointNum]->iClientBuffer);
+					aNeedsCompletion = ETrue;
+					break;
+					}
+				else
+					{
+					pEndpoint->SetClientReadPending(ETrue);
+					}
+				}
+			else if (pTfr->iTransferType == ETransferTypeReadUntilShort)
+				{
+				TInt nRx = pEndpoint->RxBytesAvailable();
+				TInt maxPacketSize = pEndpoint->EndpointInfo()->iSize;
+				if( (pTfr->iTransferSize <= nRx) ||
+					(nRx < maxPacketSize) ||
+					pEndpoint->iDmaBuffers->ShortPacketExists())
+					{
+					__KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read data: data available complete"));
+					r = pEndpoint->CopyToClient(iClient,iClientAsynchNotify[aEndpointNum]->iClientBuffer);
+					aNeedsCompletion = ETrue;
+					}
+				else
+					{
+					pEndpoint->SetClientReadPending(ETrue);
+					}
+				}
+			}
+		r = pEndpoint->TryToStartRead(EFalse);
+		if (r != KErrNone)
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("DoRequest Read: couldn't start read"));
+			r = KErrNone;									// Reader full isn't a userside error;
+			}
+		break;
+		}
+
+	case ETransferTypeWrite:
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("DoRequest Write 1"));
+		if (pEndpointInfo->iDir != KUsbEpDirIn &&
+			pEndpointInfo->iDir != KUsbEpDirBidirect)
+			{
+			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Write: wrong direction complete"));
+			r = KErrUsbEpBadDirection;
+			break;
+			}
+		__KTRACE_OPT(KUSB, Kern::Printf("DoRequest Write 2"));
+
+
+		TInt desLength=iClientAsynchNotify[aEndpointNum]->iClientBuffer->Length();
+		
+		if (desLength < pTfr->iTransferSize)
+			{
+			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Write: user buffer too short"));
+			r = KErrUsbTransferSize;
+			break;
+			}
+
+		__KTRACE_OPT(KUSB, Kern::Printf("DoRequest Write 3 length=%d maxlength=%d",
+										pTfr->iTransferSize, desLength));
+		// Zero length writes are acceptable
+		pEndpoint->SetClientWritePending(ETrue);
+		r = pEndpoint->TryToStartWrite(pTfr);
+		if (r != KErrNone)
+			{
+			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoRequest Write: couldn't start write"));
+			pEndpoint->SetClientWritePending(EFalse);
+			}
+		break;
+		}
+
+	default:
+		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: DoTransferAsyncReq: pTfr->iTransferType = %d not supported",
+										  pTfr->iTransferType));
+		r = KErrNotSupported;
+		break;
+		}
+ exit:
+	aNeedsCompletion = aNeedsCompletion || (r != KErrNone);
+	return r;
+	}
+
+
+//
+// Cancel an outstanding request - overriding pure virtual
+//
+TInt DLddUsbcChannel::DoCancel(TInt aReqNo)
+	{
+	TInt r = KErrNone;
+	__KTRACE_OPT(KUSB, Kern::Printf("DoCancel: 0x%x", aReqNo));
+	if (aReqNo <= iNumberOfEndpoints)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel endpoint: 0x%x", aReqNo));
+		iEndpoint[aReqNo]->CancelTransfer(iClient,iClientAsynchNotify[aReqNo]->iClientBuffer);
+		}
+	else if (aReqNo == RDevUsbcClient::ERequestAlternateDeviceStatusNotify)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel: ERequestAlternateDeviceStatusNotify 0x%x", aReqNo));
+		iDeviceStatusNeeded = EFalse;
+		iStatusFifo->FlushQueue();
+		if (iStatusChangePtr)
+			{
+			iStatusChangeReq->Data()=iController->GetDeviceStatus();
+			iStatusChangePtr = NULL;
+
+			if (iStatusChangeReq->IsReady())
+				{
+				iRequestStatus[aReqNo] = NULL;
+				Kern::QueueRequestComplete(iClient, iStatusChangeReq, KErrCancel);
+				}
+				return KErrNone;
+			}
+		}
+	else if (aReqNo == RDevUsbcClient::ERequestReEnumerate)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestReEnumerate: 0x%x", aReqNo));
+		}
+	else if (aReqNo == RDevUsbcClient::ERequestEndpointStatusNotify)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestEndpointStatusNotify: 0x%x", aReqNo));
+		CancelNotifyEndpointStatus();
+		if (iEndpointStatusChangeReq->IsReady())
+			{
+			iRequestStatus[aReqNo] = NULL;
+			Kern::QueueRequestComplete(iClient, iEndpointStatusChangeReq, KErrCancel);
+			}
+		return KErrNone;
+		}
+	else if (aReqNo == RDevUsbcClient::ERequestOtgFeaturesNotify)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel ERequestOtgFeaturesNotify: 0x%x", aReqNo));
+		CancelNotifyOtgFeatures();
+		if (iOtgFeatureChangeReq->IsReady())
+			{
+			iRequestStatus[aReqNo] = NULL;
+			Kern::QueueRequestComplete(iClient, iOtgFeatureChangeReq, KErrCancel);
+			}
+		}
+	else
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("DoCancel Unknown! 0x%x", aReqNo));
+		}
+
+		if (r == KErrNone)
+			r = KErrCancel;
+
+		CompleteBufferRequest(iClient, aReqNo, r);
+	return r;
+	}
+
+
+void DLddUsbcChannel::CancelNotifyEndpointStatus()
+	{
+	if (iEndpointStatusChangePtr)
+		{
+		TUint epBitmap = 0;
+		for (TInt i = 0; i <= iNumberOfEndpoints; i++)
+			{
+			TInt v = iController->GetEndpointStatus(this, iEndpoint[i]->RealEpNumber());
+			TUint b;
+			(v == EEndpointStateStalled) ? b = 1 : b = 0;
+			epBitmap |= b << i;
+			}
+		iEndpointStatusChangeReq->Data()=epBitmap;
+		iEndpointStatusChangePtr = NULL;
+		}
+	}
+
+
+void DLddUsbcChannel::CancelNotifyOtgFeatures()
+	{
+    if (iOtgFeatureChangePtr)
+        {
+        TUint8 features;
+        iController->GetCurrentOtgFeatures(features);
+	 iOtgFeatureChangeReq->Data()=features;
+        iOtgFeatureChangePtr = NULL;
+        }
+    }
+
+TInt DLddUsbcChannel::PinMemory(TDesC8 *aDes, TVirtualPinObject *aPinObj)
+	{
+	TInt r = KErrNone;
+	TInt  len,mlen;
+	
+	const TUint8*p = Kern::KUDesInfo(*aDes, len,mlen);
+	r=Kern::PinVirtualMemory(aPinObj, (TLinAddr) p, len);
+	return r;
+	}
+
+//Called in Client thread context
+TInt DLddUsbcChannel::SendControl(TMessageBase* aMsg)
+	{
+	TThreadMessage& m=*(TThreadMessage*)aMsg;
+	const TInt fn=m.iValue;
+	TAny *const a1=m.Ptr0();
+	TAny *const a2=m.Ptr1();
+	TInt  kern_param;
+	TEndpointDescriptorInfo epi;
+	TUsbcIfcInfo ifc;
+	TCSDescriptorInfo desInfo;
+	TInt r = KErrNone;
+
+	switch (fn)
+		{
+		
+	case RDevUsbcClient::EControlDeviceStatus:
+	case RDevUsbcClient::EControlGetAlternateSetting:
+		m.iArg[0] = &kern_param;  			// update message to point to kernel-side buffer
+		break;
+
+	case RDevUsbcClient::EControlQueryReceiveBuffer:
+	case RDevUsbcClient::EControlEndpointStatus:
+		m.iArg[1] = &kern_param;  			// update message to point to kernel-side buffer
+		break;
+
+	case RDevUsbcClient::EControlEndpointCaps:
+	case RDevUsbcClient::EControlDeviceCaps:
+	case RDevUsbcClient::EControlGetDeviceDescriptor:
+	case RDevUsbcClient::EControlSetDeviceDescriptor:
+	case RDevUsbcClient::EControlGetDeviceDescriptorSize:
+	case RDevUsbcClient::EControlGetConfigurationDescriptor:
+	case RDevUsbcClient::EControlGetConfigurationDescriptorSize:
+	case RDevUsbcClient::EControlGetDeviceQualifierDescriptor:
+	case RDevUsbcClient::EControlSetDeviceQualifierDescriptor:
+	case RDevUsbcClient::EControlGetOtherSpeedConfigurationDescriptor:
+	case RDevUsbcClient::EControlSetOtherSpeedConfigurationDescriptor:
+	case RDevUsbcClient::EControlGetStringDescriptorLangId:
+	case RDevUsbcClient::EControlGetManufacturerStringDescriptor:
+	case RDevUsbcClient::EControlSetManufacturerStringDescriptor:
+	case RDevUsbcClient::EControlGetProductStringDescriptor:
+	case RDevUsbcClient::EControlSetProductStringDescriptor:
+	case RDevUsbcClient::EControlGetSerialNumberStringDescriptor:	
+	case RDevUsbcClient::EControlSetSerialNumberStringDescriptor:
+	case RDevUsbcClient::EControlGetConfigurationStringDescriptor:
+	case RDevUsbcClient::EControlSetConfigurationStringDescriptor:
+	case RDevUsbcClient::EControlSetOtgDescriptor:
+	case RDevUsbcClient::EControlGetOtgDescriptor:
+	case RDevUsbcClient::EControlGetOtgFeatures:
+		r=PinMemory((TDesC8 *) a1, iPinObj1);
+		if(r!=KErrNone)
+			{
+			PanicClientThread(r);
+			return r;
+			}
+		break;
+
+	case RDevUsbcClient::EControlGetInterfaceDescriptor:
+	case RDevUsbcClient::EControlGetInterfaceDescriptorSize:
+	case RDevUsbcClient::EControlSetInterfaceDescriptor:
+	case RDevUsbcClient::EControlGetCSInterfaceDescriptor:
+	case RDevUsbcClient::EControlGetCSInterfaceDescriptorSize:
+	case RDevUsbcClient::EControlGetStringDescriptor:
+	case RDevUsbcClient::EControlSetStringDescriptor:
+		r=PinMemory((TDesC8 *) a2, iPinObj1);
+		if(r!=KErrNone)
+			{
+			PanicClientThread(r);
+			return r;
+			}
+		break;
+
+	case RDevUsbcClient::EControlGetEndpointDescriptor:
+	case RDevUsbcClient::EControlGetEndpointDescriptorSize:
+	case RDevUsbcClient::EControlSetEndpointDescriptor:
+	case RDevUsbcClient::EControlGetCSEndpointDescriptor:
+	case RDevUsbcClient::EControlGetCSEndpointDescriptorSize:
+		if(a1!=NULL)
+			{
+			r=Kern::PinVirtualMemory(iPinObj1, (TLinAddr)a1, sizeof(epi));
+			if(r!=KErrNone)
+				{
+				PanicClientThread(r);
+				return r;
+				}
+			kumemget(&epi, a1, sizeof(epi));
+			r=PinMemory((TDesC8 *) epi.iArg, iPinObj2);
+			if(r!=KErrNone)
+				{
+				Kern::UnpinVirtualMemory(iPinObj1);
+				PanicClientThread(r);
+				return r;
+				}
+			}
+		break;
+
+	case RDevUsbcClient::EControlSetInterface:
+		if(a2!=NULL)
+			{
+			r=Kern::PinVirtualMemory(iPinObj1, (TLinAddr)a2, sizeof(ifc));
+			if(r!=KErrNone)
+				{
+				PanicClientThread(r);
+				return r;
+				}	
+			kumemget(&ifc, a2, sizeof(ifc));				
+			r=PinMemory((TDesC8 *) ifc.iInterfaceData, iPinObj2);
+			if(r!=KErrNone)
+				{
+				Kern::UnpinVirtualMemory(iPinObj1);
+				PanicClientThread(r);
+				return r;
+				}
+			}
+		break;
+
+	case RDevUsbcClient::EControlSetCSInterfaceDescriptor:
+	case RDevUsbcClient::EControlSetCSEndpointDescriptor:
+		if(a1!=NULL)
+			{
+			r=Kern::PinVirtualMemory(iPinObj1, (TLinAddr)a1, sizeof(desInfo));
+			if(r!=KErrNone)
+				{
+				PanicClientThread(r);
+				return r;
+				}
+			kumemget(&desInfo, a1, sizeof(desInfo));
+			r=PinMemory((TDesC8 *) desInfo.iArg, iPinObj2);
+			if(r!=KErrNone)
+				{
+				Kern::UnpinVirtualMemory(iPinObj1);
+				PanicClientThread(r);
+				return r;
+				}
+			}
+		break;
+	}
+
+
+	//Send Message and wait for synchronous complete	
+	r = DLogicalChannel::SendMsg(aMsg);
+	
+	
+	
+	switch (fn)
+		{
+	case RDevUsbcClient::EControlDeviceStatus:
+	case RDevUsbcClient::EControlGetAlternateSetting:
+		umemput32(a1, &kern_param, sizeof(kern_param));
+		break;
+
+	case RDevUsbcClient::EControlQueryReceiveBuffer:
+	case RDevUsbcClient::EControlEndpointStatus:
+		umemput32(a2, &kern_param, sizeof(kern_param));
+		break;
+
+	case RDevUsbcClient::EControlDeviceCaps:
+	case RDevUsbcClient::EControlEndpointCaps:
+	case RDevUsbcClient::EControlGetDeviceDescriptor:
+	case RDevUsbcClient::EControlSetDeviceDescriptor:
+	case RDevUsbcClient::EControlGetDeviceDescriptorSize:
+	case RDevUsbcClient::EControlGetConfigurationDescriptor:
+	case RDevUsbcClient::EControlGetConfigurationDescriptorSize:
+	case RDevUsbcClient::EControlGetDeviceQualifierDescriptor:
+	case RDevUsbcClient::EControlSetDeviceQualifierDescriptor:
+	case RDevUsbcClient::EControlGetOtherSpeedConfigurationDescriptor:
+	case RDevUsbcClient::EControlSetOtherSpeedConfigurationDescriptor:
+	case RDevUsbcClient::EControlGetStringDescriptorLangId:
+	case RDevUsbcClient::EControlGetManufacturerStringDescriptor:
+	case RDevUsbcClient::EControlSetManufacturerStringDescriptor:
+	case RDevUsbcClient::EControlGetProductStringDescriptor:
+	case RDevUsbcClient::EControlSetProductStringDescriptor:
+	case RDevUsbcClient::EControlGetSerialNumberStringDescriptor:	
+	case RDevUsbcClient::EControlSetSerialNumberStringDescriptor:
+	case RDevUsbcClient::EControlGetConfigurationStringDescriptor:
+	case RDevUsbcClient::EControlSetConfigurationStringDescriptor:
+	case RDevUsbcClient::EControlSetOtgDescriptor:
+	case RDevUsbcClient::EControlGetOtgDescriptor:
+	case RDevUsbcClient::EControlGetOtgFeatures:
+		if(a1!=NULL)
+			{
+			Kern::UnpinVirtualMemory(iPinObj1);
+			}
+		break;
+
+	case RDevUsbcClient::EControlGetInterfaceDescriptor:
+	case RDevUsbcClient::EControlGetInterfaceDescriptorSize:
+	case RDevUsbcClient::EControlSetInterfaceDescriptor:
+	case RDevUsbcClient::EControlGetCSInterfaceDescriptor:
+	case RDevUsbcClient::EControlGetCSInterfaceDescriptorSize:
+	case RDevUsbcClient::EControlGetStringDescriptor:
+	case RDevUsbcClient::EControlSetStringDescriptor:
+		if(a2!=NULL)
+			{
+			Kern::UnpinVirtualMemory(iPinObj1);
+			}
+		break;
+	
+	case RDevUsbcClient::EControlGetEndpointDescriptor:
+	case RDevUsbcClient::EControlGetEndpointDescriptorSize:
+	case RDevUsbcClient::EControlSetEndpointDescriptor:
+	case RDevUsbcClient::EControlGetCSEndpointDescriptor:
+	case RDevUsbcClient::EControlGetCSEndpointDescriptorSize:
+	case RDevUsbcClient::EControlSetCSInterfaceDescriptor:
+	case RDevUsbcClient::EControlSetCSEndpointDescriptor:
+		if(a1!=NULL)
+			{
+			Kern::UnpinVirtualMemory(iPinObj1);
+			Kern::UnpinVirtualMemory(iPinObj2);
+			}
+		break;
+
+	case RDevUsbcClient::EControlSetInterface:
+		if(a2!=NULL)
+			{
+			Kern::UnpinVirtualMemory(iPinObj1);
+			Kern::UnpinVirtualMemory(iPinObj2);
+			}
+		break;
+		}
+
+	return r;
+    }
+
+
+TInt DLddUsbcChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("DoControl: %d", aFunction));
+
+	TInt r = KErrNone;
+	TInt ep;
+	TUsbcEndpoint* pEndpoint;
+	TPtrC8 pZeroDesc(NULL, 0);
+	TEndpointDescriptorInfo epInfo;
+	TUsbcIfcInfo ifcInfo;
+	TCSDescriptorInfo desInfo;
+	TUsbcEndpointResource epRes;
+	TInt bandwidthPriority;
+
+	switch (aFunction)
+		{
+	case RDevUsbcClient::EControlEndpointZeroRequestError:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroRequestError"));
+		r = KErrNone;
+		if (iOwnsDeviceControl || (iValidInterface && iDeviceState == EUsbcDeviceStateConfigured))
+			{
+			iController->Ep0Stall(this);
+			}
+		else
+			{
+			if (iDeviceState != EUsbcDeviceStateConfigured)
+				r = KErrUsbDeviceNotConfigured;
+			else
+				r = KErrUsbInterfaceNotReady;
+			}
+		break;
+
+	case RDevUsbcClient::EControlGetAlternateSetting:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetAlternateSetting"));
+		if (iValidInterface && iDeviceState == EUsbcDeviceStateConfigured)
+			{
+			r = iController->GetInterfaceNumber(this, *(TInt*)a1);
+			}
+		else
+			{
+			if (iDeviceState != EUsbcDeviceStateConfigured)
+				r = KErrUsbDeviceNotConfigured;
+			else
+				r = KErrUsbInterfaceNotReady;
+			}
+		break;
+
+	case RDevUsbcClient::EControlDeviceStatus:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceStatus"));
+		*(TInt*)a1 = iController->GetDeviceStatus();
+		break;
+
+	case RDevUsbcClient::EControlEndpointStatus:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointStatus"));
+		if (iValidInterface && ValidEndpoint((TInt) a1))
+			{
+			pEndpoint = iEndpoint[(TInt)a1];
+			if (pEndpoint == NULL)
+				r = KErrNotSupported;
+			else
+				{
+				*(TInt*)a2 = iController->GetEndpointStatus(this, iEndpoint[(TInt)a1]->RealEpNumber());
+				}
+			}
+		else
+			{
+			if (iDeviceState != EUsbcDeviceStateConfigured)
+				r = KErrUsbDeviceNotConfigured;
+			else
+				r = KErrUsbInterfaceNotReady;
+			}
+		break;
+
+	case RDevUsbcClient::EControlQueryReceiveBuffer:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlQueryReceiveBuffer"));
+		if (iValidInterface && ValidEndpoint((TInt) a1))
+			{
+			pEndpoint=iEndpoint[(TInt) a1];
+			if (pEndpoint == NULL)
+				r = KErrNotSupported;
+			else if (pEndpoint->EndpointInfo()->iDir != KUsbEpDirIn)
+				{
+				__KTRACE_OPT(KUSB, Kern::Printf("  bytes = %d", pEndpoint->RxBytesAvailable()));
+				*(TInt*)a2 = pEndpoint->RxBytesAvailable();
+				}
+			}
+		else
+			{
+			if (iDeviceState != EUsbcDeviceStateConfigured)
+				r = KErrUsbDeviceNotConfigured;
+			else
+				r = KErrUsbInterfaceNotReady;
+			}
+		break;
+
+	case RDevUsbcClient::EControlEndpointCaps:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointCaps"));
+		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+		if (r != KErrNone)
+			PanicClientThread(r);
+		iController->EndpointCaps(this, *((TDes8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlDeviceCaps:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceCaps"));
+		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+		if (r != KErrNone)
+			PanicClientThread(r);
+		iController->DeviceCaps(this, *((TDes8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlSendEp0StatusPacket:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSendEp0StatusPacket"));
+		iController->SendEp0StatusPacket(this);
+		break;
+
+	case RDevUsbcClient::EControlHaltEndpoint:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlHaltEndpoint"));
+		if (iValidInterface && ValidEndpoint((TInt) a1))
+			{
+			r = iController->HaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
+			}
+		else
+			{
+			if (iDeviceState != EUsbcDeviceStateConfigured)
+				r = KErrUsbDeviceNotConfigured;
+			else
+				r = KErrUsbInterfaceNotReady;
+			}
+		break;
+
+	case RDevUsbcClient::EControlClearHaltEndpoint:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlClearHaltEndpoint"));
+		if (iValidInterface && ValidEndpoint((TInt) a1))
+			{
+			r = iController->ClearHaltEndpoint(this, iEndpoint[(TInt)a1]->RealEpNumber());
+			}
+		else
+			{
+			if (iDeviceState != EUsbcDeviceStateConfigured)
+				r = KErrUsbDeviceNotConfigured;
+			else
+				r = KErrUsbInterfaceNotReady;
+			}
+		break;
+
+	case RDevUsbcClient::EControlDumpRegisters:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlDumpRegisters"));
+		iController->DumpRegisters();
+		break;
+
+	case RDevUsbcClient::EControlReleaseDeviceControl:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseDeviceControl"));
+		iController->ReleaseDeviceControl(this);
+		iOwnsDeviceControl = EFalse;
+		break;
+
+	case RDevUsbcClient::EControlEndpointZeroMaxPacketSizes:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlEndpointZeroMaxPacketSizes"));
+		r = iController->EndpointZeroMaxPacketSizes();
+		break;
+
+	case RDevUsbcClient::EControlSetEndpointZeroMaxPacketSize:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointZeroMaxPacketSize"));
+		r = iController->SetEndpointZeroMaxPacketSize(reinterpret_cast<TInt>(a1));
+		break;
+
+	case RDevUsbcClient::EControlGetEndpointZeroMaxPacketSize:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointZeroMaxPacketSize"));
+		r = iController->Ep0PacketSize();
+		break;
+
+	case RDevUsbcClient::EControlGetDeviceDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptor"));
+		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+		if (r != KErrNone)
+			PanicClientThread(r);
+		r = iController->GetDeviceDescriptor(iClient, *((TDes8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlSetDeviceDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceDescriptor"));
+		if (a1 != NULL)
+			r = iController->SetDeviceDescriptor(iClient, *((TDes8*) a1));
+		else
+			r = KErrArgument;
+		break;
+
+	case RDevUsbcClient::EControlGetDeviceDescriptorSize:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceDescriptorSize"));
+		if (a1 != NULL)
+			r = iController->GetDeviceDescriptorSize(iClient, *((TDes8*) a1));
+		else
+			r = KErrArgument;
+		break;
+
+	case RDevUsbcClient::EControlGetConfigurationDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptor"));
+		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
+		if (r != KErrNone)
+			PanicClientThread(r);
+		r = iController->GetConfigurationDescriptor(iClient, *((TDes8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlGetConfigurationDescriptorSize:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationDescriptorSize"));
+		if (a1 != NULL)
+			{
+			r = iController->GetConfigurationDescriptorSize(iClient, *((TDes8*) a1));
+			}
+		else
+			r = KErrArgument;
+		break;
+
+	case RDevUsbcClient::EControlSetConfigurationDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationDescriptor"));
+		r = iController->SetConfigurationDescriptor(iClient, *((TDes8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlGetInterfaceDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptor"));
+		r = iController->GetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
+		break;
+
+	case RDevUsbcClient::EControlGetInterfaceDescriptorSize:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetInterfaceDescriptorSize"));
+		r = iController->GetInterfaceDescriptorSize(iClient, this, (TInt) a1, *(TDes8*) a2);
+		break;
+
+	case RDevUsbcClient::EControlSetInterfaceDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterfaceDescriptor"));
+		r = iController->SetInterfaceDescriptor(iClient, this, (TInt) a1, *((TDes8*) a2));
+		break;
+
+	case RDevUsbcClient::EControlGetEndpointDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptor"));
+		r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+		if (r != KErrNone)
+			PanicClientThread(r);
+		ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+		r = iController->GetEndpointDescriptor(iClient, this, epInfo.iSetting,
+											   ep, *(TDes8*) epInfo.iArg);
+		break;
+
+	case RDevUsbcClient::EControlGetEndpointDescriptorSize:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetEndpointDescriptorSize"));
+		r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+		if (r != KErrNone)
+			PanicClientThread(r);
+		ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+		r = iController->GetEndpointDescriptorSize(iClient, this, epInfo.iSetting,
+												   ep, *(TDes8*) epInfo.iArg);
+		break;
+
+	case RDevUsbcClient::EControlSetEndpointDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetEndpointDescriptor"));
+		r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+		if (r != KErrNone)
+			PanicClientThread(r);
+		ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+		r = iController->SetEndpointDescriptor(iClient, this, epInfo.iSetting,
+											   ep, *(TDes8*)epInfo.iArg);
+		break;
+
+	case RDevUsbcClient::EControlGetDeviceQualifierDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetDeviceQualifierDescriptor"));
+		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0, 0, iClient);
+		if (r != KErrNone)
+			PanicClientThread(r);
+		r = iController->GetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlSetDeviceQualifierDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceQualifierDescriptor"));
+		if (a1 != NULL)
+			r = iController->SetDeviceQualifierDescriptor(iClient, *((TDes8*) a1));
+		else
+			r = KErrArgument;
+		break;
+
+	case RDevUsbcClient::EControlGetOtherSpeedConfigurationDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetOtherSpeedConfigurationDescriptor"));
+		r = Kern::ThreadDesWrite(iClient, a1, pZeroDesc, 0 , 0, iClient);
+		if (r != KErrNone)
+			PanicClientThread(r);
+		r = iController->GetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlSetOtherSpeedConfigurationDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetOtherSpeedConfigurationDescriptor"));
+		r = iController->SetOtherSpeedConfigurationDescriptor(iClient, *((TDes8*) a1));
+		break;
+
+
+	case RDevUsbcClient::EControlGetCSInterfaceDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptor"));
+		r = iController->GetCSInterfaceDescriptorBlock(iClient, this, (TInt) a1, *((TDes8*) a2));
+		break;
+
+	case RDevUsbcClient::EControlGetCSInterfaceDescriptorSize:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSInterfaceDescriptorSize"));
+		r = iController->GetCSInterfaceDescriptorBlockSize(iClient, this, (TInt) a1, *(TDes8*) a2);
+		break;
+
+	case RDevUsbcClient::EControlGetCSEndpointDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptor"));
+		r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+		if (r != KErrNone)
+			PanicClientThread(r);
+		ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+		r = iController->GetCSEndpointDescriptorBlock(iClient, this, epInfo.iSetting,
+													  ep, *(TDes8*) epInfo.iArg);
+		break;
+
+	case RDevUsbcClient::EControlGetCSEndpointDescriptorSize:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetCSEndpointDescriptorSize"));
+		r = Kern::ThreadRawRead(iClient, a1, &epInfo, sizeof(epInfo));
+		if (r != KErrNone)
+			PanicClientThread(r);
+		ep = EpFromAlternateSetting(epInfo.iSetting, epInfo.iEndpoint);
+		r = iController->GetCSEndpointDescriptorBlockSize(iClient, this, epInfo.iSetting,
+														  ep, *(TDes8*) epInfo.iArg);
+		break;
+
+	case RDevUsbcClient::EControlSignalRemoteWakeup:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSignalRemoteWakeup"));
+		r = iController->SignalRemoteWakeup();
+		break;
+
+	case RDevUsbcClient::EControlDeviceDisconnectFromHost:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceDisconnectFromHost"));
+		r = iController->UsbDisconnect();
+		break;
+
+	case RDevUsbcClient::EControlDeviceConnectToHost:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlDeviceConnectToHost"));
+		r = iController->UsbConnect();
+		break;
+
+	case RDevUsbcClient::EControlDevicePowerUpUdc:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlDevicePowerUpUdc"));
+		r = iController->PowerUpUdc();
+		break;
+
+	case RDevUsbcClient::EControlSetDeviceControl:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl"));
+		r = iController->SetDeviceControl(this);
+		if (r == KErrNone)
+			{
+			iOwnsDeviceControl = ETrue;
+			if (iEndpoint[0] == NULL)
+				{
+				__KTRACE_OPT(KUSB, Kern::Printf("EControlSetDeviceControl 11"));
+				r = SetupEp0();
+				if (r != KErrNone)
+					{
+					__KTRACE_OPT(KPANIC, Kern::Printf("  Error: SetupEp0() failed"));
+					iController->ReleaseDeviceControl(this);
+					DestroyEp0();
+					iOwnsDeviceControl = EFalse;
+					}
+				iEndpoint[0]->TryToStartRead(EFalse);
+				}
+			}
+		else
+			r = KErrInUse;
+		break;
+
+	case RDevUsbcClient::EControlCurrentlyUsingHighSpeed:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlCurrentlyUsingHighSpeed"));
+		r = iController->CurrentlyUsingHighSpeed();
+		break;
+
+	case RDevUsbcClient::EControlSetInterface:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetInterface"));
+		r = Kern::ThreadRawRead(iClient, a2, &ifcInfo, sizeof(ifcInfo));
+		if (r != KErrNone)
+			PanicClientThread(r);
+		if (iValidInterface && (iDeviceState == EUsbcDeviceStateConfigured))
+			{
+			r = KErrGeneral;
+			}
+		else
+			{
+			bandwidthPriority = ifcInfo.iBandwidthPriority;
+			if ((bandwidthPriority & 0xffffff00) ||
+				((bandwidthPriority & 0x0f) >= KUsbcDmaBufMaxPriorities) ||
+				(((bandwidthPriority >> 4) & 0x0f) >= KUsbcDmaBufMaxPriorities))
+				{
+				r = KErrArgument;
+				}
+			else
+				{
+				r = SetInterface((TInt) a1, &ifcInfo);
+				}
+			}
+			
+		break;
+
+	case RDevUsbcClient::EControlReleaseInterface:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlReleaseInterface"));
+		r = iController->ReleaseInterface(this, (TInt) a1);
+		if (r == KErrNone)
+			{
+			DestroyInterface((TUint) a1);
+			}
+		else
+			{
+			__KTRACE_OPT(KPANIC, Kern::Printf("  Error in PIL: LDD interface won't be released."));
+			}
+		break;
+
+	case RDevUsbcClient::EControlSetCSInterfaceDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSInterfaceDescriptor"));
+		r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
+		if (r != KErrNone)
+			PanicClientThread(r);
+		r = iController->SetCSInterfaceDescriptorBlock(iClient, this, desInfo.iSetting,
+													   *reinterpret_cast<const TDes8*>(desInfo.iArg),
+													   desInfo.iSize);
+		break;
+
+	case RDevUsbcClient::EControlSetCSEndpointDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetCSEndpointDescriptor"));
+		r = Kern::ThreadRawRead(iClient, a1, &desInfo, sizeof(desInfo));
+		if (r != KErrNone)
+			PanicClientThread(r);
+		ep = EpFromAlternateSetting(desInfo.iSetting, desInfo.iEndpoint);
+		r = iController->SetCSEndpointDescriptorBlock(iClient, this, desInfo.iSetting, ep,
+													  *reinterpret_cast<const TDes8*>(desInfo.iArg),
+													  desInfo.iSize);
+		break;
+
+	case RDevUsbcClient::EControlGetStringDescriptorLangId:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptorLangId"));
+		r = iController->GetStringDescriptorLangId(iClient, *((TDes8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlSetStringDescriptorLangId:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptorLangId"));
+		r = iController->SetStringDescriptorLangId(reinterpret_cast<TUint>(a1));
+		break;
+
+	case RDevUsbcClient::EControlGetManufacturerStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetManufacturerStringDescriptor"));
+		r = iController->GetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlSetManufacturerStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetManufacturerStringDescriptor"));
+		r = iController->SetManufacturerStringDescriptor(iClient, *((TPtr8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlRemoveManufacturerStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveManufacturerStringDescriptor"));
+		r = iController->RemoveManufacturerStringDescriptor();
+		break;
+
+	case RDevUsbcClient::EControlGetProductStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetProductStringDescriptor"));
+		r = iController->GetProductStringDescriptor(iClient, *((TPtr8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlSetProductStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetProductStringDescriptor"));
+		r = iController->SetProductStringDescriptor(iClient, *((TPtr8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlRemoveProductStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveProductStringDescriptor"));
+		r = iController->RemoveProductStringDescriptor();
+		break;
+
+	case RDevUsbcClient::EControlGetSerialNumberStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetSerialNumberStringDescriptor"));
+		r = iController->GetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlSetSerialNumberStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetSerialNumberStringDescriptor"));
+		r = iController->SetSerialNumberStringDescriptor(iClient, *((TPtr8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlRemoveSerialNumberStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveSerialNumberStringDescriptor"));
+		r = iController->RemoveSerialNumberStringDescriptor();
+		break;
+
+	case RDevUsbcClient::EControlGetConfigurationStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetConfigurationStringDescriptor"));
+		r = iController->GetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlSetConfigurationStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetConfigurationStringDescriptor"));
+		r = iController->SetConfigurationStringDescriptor(iClient, *((TPtr8*) a1));
+		break;
+
+	case RDevUsbcClient::EControlRemoveConfigurationStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveConfigurationStringDescriptor"));
+		r = iController->RemoveConfigurationStringDescriptor();
+		break;
+
+	case RDevUsbcClient::EControlGetStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlGetStringDescriptor"));
+		r = iController->GetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
+		break;
+
+	case RDevUsbcClient::EControlSetStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlSetStringDescriptor"));
+		r = iController->SetStringDescriptor(iClient, (TUint8) (TInt) a1, *((TPtr8*) a2));
+		break;
+
+	case RDevUsbcClient::EControlRemoveStringDescriptor:
+		__KTRACE_OPT(KUSB, Kern::Printf("EControlRemoveStringDescriptor"));
+		r = iController->RemoveStringDescriptor((TUint8) (TInt) a1);
+		break;
+
+	case RDevUsbcClient::EControlAllocateEndpointResource:
+		epRes = (TUsbcEndpointResource)((TInt) a2);
+		if (!ValidEndpoint((TInt)a1))
+			{
+			r = KErrUsbEpNotInInterface;
+			}
+		else
+			{
+			r = iController->AllocateEndpointResource(this, iEndpoint[(TInt)a1]->RealEpNumber(), epRes);
+			}
+		break;
+
+	case RDevUsbcClient::EControlDeAllocateEndpointResource:
+		epRes = (TUsbcEndpointResource)((TInt) a2);
+		if (!ValidEndpoint((TInt)a1))
+			{
+			r = KErrUsbEpNotInInterface;
+			}
+		else
+			{
+			r = iController->DeAllocateEndpointResource(this, iEndpoint[(TInt)a1]->RealEpNumber(), epRes);
+			}
+		break;
+
+	case RDevUsbcClient::EControlQueryEndpointResourceUse:
+		epRes = (TUsbcEndpointResource)((TInt) a2);
+		if (!ValidEndpoint((TInt)a1))
+			{
+			r = KErrUsbEpNotInInterface;
+			}
+		else
+			{
+			r = iController->QueryEndpointResource(this, iEndpoint[(TInt)a1]->RealEpNumber(), epRes);
+			}
+		break;
+
+	case RDevUsbcClient::EControlSetOtgDescriptor:
+		{
+		r = iController->SetOtgDescriptor(iClient, *((const TDesC8*)a1));
+		}
+		break;
+
+	case RDevUsbcClient::EControlGetOtgDescriptor:
+		{
+		r = iController->GetOtgDescriptor(iClient, *((TDes8*)a1));
+		}
+		break;
+
+	case RDevUsbcClient::EControlGetOtgFeatures:
+		{
+		r = iController->GetOtgFeatures(iClient, *((TDes8*)a1));
+		}
+		break;
+
+    default:
+		__KTRACE_OPT(KUSB, Kern::Printf("Function code not supported"));
+		r = KErrNotSupported;
+		}
+
+	return r;
+	}
+
+
+TInt DLddUsbcChannel::SetInterface(TInt aInterfaceNumber, TUsbcIfcInfo* aInfoBuf)
+	{
+	TUsbcInterfaceInfoBuf ifc_info_buf;
+	TUsbcInterfaceInfoBuf* const ifc_info_buf_ptr = aInfoBuf->iInterfaceData;
+	const TInt srcLen = Kern::ThreadGetDesLength(iClient, ifc_info_buf_ptr);
+	if (srcLen < ifc_info_buf.Length())
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface can't copy"));
+		PanicClientThread(EDesOverflow);
+		}
+
+	TInt r = Kern::ThreadDesRead(iClient, ifc_info_buf_ptr, ifc_info_buf, 0, KChunkShiftBy0);
+	if (r != KErrNone)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface Copy failed reason=%d", r));
+		PanicClientThread(r);
+		}
+
+	TUsbcEndpointInfo* pEndpointData = ifc_info_buf().iEndpointData;
+
+	// If an alternate interface is being asked for then do nothing,
+	// just pass it down to the Controller.
+	const TInt num_endpoints = ifc_info_buf().iTotalEndpointsUsed;
+	__KTRACE_OPT(KUSB, Kern::Printf("SetInterface num_endpoints=%d", num_endpoints));
+
+	// [The next 4 variables have to be initialized here because of the goto's that follow.]
+	// Both IN and OUT buffers will be fully cached:
+	const TUint32 cacheAttribs = EMapAttrSupRw | EMapAttrCachedMax;
+	const TUint32 bandwidthPriority = aInfoBuf->iBandwidthPriority;
+	TInt totalINBufferSize = 0;
+	TInt totalOUTBufferSize = 0;
+
+	TInt real_ep_numbers[6] = {-1, -1, -1, -1, -1, -1};
+
+    // See if PIL will accept this interface
+	__KTRACE_OPT(KUSB, Kern::Printf("SetInterface Calling controller"));
+	r = iController->SetInterface(this,
+								  iClient,
+								  aInterfaceNumber,
+								  ifc_info_buf().iClass,
+								  aInfoBuf->iString,
+								  ifc_info_buf().iTotalEndpointsUsed,
+								  ifc_info_buf().iEndpointData,
+								  &real_ep_numbers,
+								  ifc_info_buf().iFeatureWord);
+
+	__KTRACE_OPT(KUSB, Kern::Printf("SetInterface controller returned %d", r));
+	if (r != KErrNone)
+		{
+		__KTRACE_OPT(KPANIC, Kern::Printf("SetInterface failed reason=%d", r));
+		return r;
+		}
+
+	// [The next variable has to be initialized here because of the goto's that follow.]
+	TUsbcAlternateSettingList* alternateSettingListRec;
+
+	// ep0
+	if (iEndpoint[0] == NULL)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface 11"));
+		r = SetupEp0();
+		if (r != KErrNone)
+			{
+			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: SetupEp0() failed"));
+			DestroyEp0();
+			goto F1;
+			}
+		}
+
+	alternateSettingListRec = new TUsbcAlternateSettingList;
+	if (!alternateSettingListRec)
+		{
+		r = KErrNoMemory;
+		goto F1;
+		}
+
+	// other endpoints
+	for (TInt i = 1; i <= num_endpoints; i++, pEndpointData++)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d", i));
+		if (!ValidateEndpoint(pEndpointData))
+			{
+			r = KErrUsbBadEndpoint;
+			goto F2;
+			}
+		TUsbcEndpoint* ep = new TUsbcEndpoint(this, iController, pEndpointData, i, bandwidthPriority);
+		alternateSettingListRec->iEndpoint[i] = ep;
+		if (!ep)
+			{
+			r = KErrNoMemory;
+			goto F2;
+			}
+		if (ep->Construct() != KErrNone)
+			{
+			r = KErrNoMemory;
+			goto F2;
+			}
+		if (pEndpointData->iDir == KUsbEpDirIn)
+			{
+			totalINBufferSize += ep->BufferTotalSize();
+			__KTRACE_OPT(KUSB, Kern::Printf("IN buffering now %d", totalINBufferSize));
+			}
+		else if (pEndpointData->iDir == KUsbEpDirOut)
+			{
+			totalOUTBufferSize += ep->BufferTotalSize();
+			__KTRACE_OPT(KUSB, Kern::Printf("OUT buffering now %d", totalOUTBufferSize));
+			}
+		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d rec=0x%08x ep==0x%08x",
+										i, alternateSettingListRec, ep));
+		}
+
+	// chain in this alternate setting
+	alternateSettingListRec->iNext = iAlternateSettingList;
+	iAlternateSettingList = alternateSettingListRec;
+	alternateSettingListRec->iSetting = aInterfaceNumber;
+	alternateSettingListRec->iNumberOfEndpoints = num_endpoints;
+
+	// Record the 'real' endpoint number used by the PDD in both the Ep and
+	// the Req callback:
+	for (TInt i = 1; i <= num_endpoints; i++)
+		{
+		alternateSettingListRec->iEndpoint[i]->SetRealEpNumber(real_ep_numbers[i]);
+		}
+
+	if (totalOUTBufferSize != 0)
+		{
+		// maximally cached always
+		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface setting up OUT buffering size=%d", totalOUTBufferSize));
+		iHwChunkOUT = SetupInterfaceMemory(totalOUTBufferSize, iHwChunkOUT, KUsbEpDirOut, cacheAttribs);
+		if (iHwChunkOUT == NULL)
+			{
+			__KTRACE_OPT(KPANIC, Kern::Printf("SetInterface can't get chunk for OUT buffering size=%d reason=%d",
+											  totalOUTBufferSize, r));
+			r = KErrNoMemory;
+			goto KillAll;
+			}
+		}
+	if (totalINBufferSize != 0)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface setting up IN buffering size=%d", totalINBufferSize));
+		iHwChunkIN = SetupInterfaceMemory(totalINBufferSize, iHwChunkIN, KUsbEpDirIn, cacheAttribs);
+		if (iHwChunkIN == NULL)
+			{
+			__KTRACE_OPT(KPANIC, Kern::Printf("SetInterface can't get chunk for IN buffering size=%d reason=%d",
+											  totalOUTBufferSize, r));
+			r = KErrNoMemory;
+			goto KillAll;
+			}
+		}
+	__KTRACE_OPT(KUSB, Kern::Printf("SetInterface ready to exit"));
+
+	if (aInterfaceNumber == 0)
+		{
+		// make sure we're ready to go with the main interface
+		iValidInterface = ETrue;
+		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface SelectAlternateSetting"));
+		SelectAlternateSetting(0);
+		}
+	return KErrNone;
+
+ KillAll:
+	__KTRACE_OPT(KUSB, Kern::Printf("Destroying all interfaces"));
+	DestroyAllInterfaces();
+	DestroyEp0();
+	return r;
+
+ F2:
+	delete alternateSettingListRec;
+	//Fall through
+ 
+ F1:
+#if _DEBUG
+	TInt r1 = iController->ReleaseInterface(this, aInterfaceNumber);
+	__KTRACE_OPT(KUSB, Kern::Printf("Release Interface controller returned %d", r1));
+#else
+	(void)	iController->ReleaseInterface(this, aInterfaceNumber);
+#endif
+	return r;
+	}
+
+
+DPlatChunkHw* DLddUsbcChannel::SetupInterfaceMemory(TInt aBufferSize, DPlatChunkHw* aHwChunk,
+													TUint aDirection, TUint32 aCacheAttribs)
+	{
+	TUint8* oldBase = NULL;
+	if (aHwChunk != NULL)
+		oldBase = reinterpret_cast<TUint8*>(aHwChunk->LinearAddress());
+
+	DPlatChunkHw* chunk = ReAllocate(aBufferSize, aHwChunk, aCacheAttribs);
+	if (chunk == NULL)
+		{
+		// lost all interfaces:
+		// Tell Controller to release Interface and h/w resources associated with this
+		iController->DeRegisterClient(this);
+		}
+	else
+		{
+		// Parcel out the memory between endpoints
+		TUint8* newBase = reinterpret_cast<TUint8*>(chunk->LinearAddress());
+		TBool needsRebase = (newBase != oldBase);
+		TUint8* pBuf = newBase;
+		TUint8* pBufIf = pBuf;							   // this is where an interface's ep buffering starts
+		TUsbcAlternateSettingList* asRec = iAlternateSettingList;
+		// the current interface
+		__KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory rebasing setting=%d", asRec->iSetting));
+		RebaseInterfaceMemory(asRec, pBuf, aDirection);
+		// now the others if a rebase has occured
+		if (needsRebase)
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory rebasing "));
+			asRec = asRec->iNext;
+			while (asRec)
+				{
+				// Interfaces are not concurrent so they can all start at the same logical address
+				__KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory rebasing setting=%d", asRec->iSetting));
+				pBuf = pBufIf;
+				RebaseInterfaceMemory(asRec, pBuf, aDirection);
+				asRec = asRec->iNext;
+				}
+			}
+		__KTRACE_OPT(KUSB, Kern::Printf("SetInterface numberOfEndpoints"));
+		}
+	return chunk;
+	}
+
+
+TInt DLddUsbcChannel::SetupEp0()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("SetupEp0 entry %x", this));
+	TInt ep0Size = iController->Ep0PacketSize();
+	TUsbcEndpointInfo ep0Info = TUsbcEndpointInfo(KUsbEpTypeControl, KUsbEpDirBidirect, ep0Size);
+	TUsbcEndpoint* ep0 = new TUsbcEndpoint(this, iController, &ep0Info, 0, 0);
+	if (ep0 == NULL)
+		{
+		return KErrNoMemory;
+		}
+	// In case we have to return early:
+	iEndpoint[0] = ep0;
+	TInt r = ep0->Construct();
+	if (r != KErrNone)
+		{
+		return KErrNoMemory;
+		}
+	TInt bufferSize = ep0->BufferTotalSize();
+	TUint32 cacheAttribs = EMapAttrSupRw | EMapAttrCachedMax;
+	iHwChunkEp0 = Allocate(bufferSize, cacheAttribs);
+	if (iHwChunkEp0 == NULL)
+		{
+		return KErrNoMemory;
+		}
+	iBufferSizeEp0 = bufferSize;
+	iBufferBaseEp0 = (TUint8*) iHwChunkEp0->LinearAddress();
+	ep0->SetBufferBase(iBufferBaseEp0);
+	ep0->SetRealEpNumber(0);
+	__KTRACE_OPT(KUSB, Kern::Printf("SetupEp0 60 buffersize=%d", iBufferSizeEp0));
+	__KTRACE_OPT(KUSB, Kern::Printf("SetupEp0 exit bufferbase=0x%08x", iBufferBaseEp0));
+	return KErrNone;
+	}
+
+
+void DLddUsbcChannel::RebaseInterfaceMemory(TUsbcAlternateSettingList* aAlternateSettingListRec,
+											TUint8* aBase, TUint aDirection)
+	{
+	TUint8* pBuf = aBase;
+	__KTRACE_OPT(KUSB, Kern::Printf("RebaseInterfaceMemory buffer base rec= 0x%08x", aAlternateSettingListRec));
+	for (TInt i = 1; i <= aAlternateSettingListRec->iNumberOfEndpoints; i++)
+		{
+		TUsbcEndpoint* ep = aAlternateSettingListRec->iEndpoint[i];
+		if (ep != NULL && (ep->EndpointInfo()->iDir == aDirection))
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("RebaseInterfaceMemory buffer base for ep%d 0x%08x 0x%08x",
+											i, pBuf, ep));
+			pBuf = ep->SetBufferBase(pBuf);
+			}
+		else
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("RebaseInterfaceMemory ep%d wrong direction", i));
+			}
+		}
+	}
+
+
+void DLddUsbcChannel::DestroyAllInterfaces()
+	{
+	// Removes all interfaces
+	TUsbcAlternateSettingList* alternateSettingListRec = iAlternateSettingList;
+	while (alternateSettingListRec)
+		{
+		iController->ReleaseInterface(this, alternateSettingListRec->iSetting);
+		TUsbcAlternateSettingList* alternateSettingListRecNext = alternateSettingListRec->iNext;
+		delete alternateSettingListRec;
+		alternateSettingListRec = alternateSettingListRecNext;
+		}
+	iNumberOfEndpoints = 0;
+	iAlternateSettingList = NULL;
+
+	ClosePhysicalChunk(iHwChunkIN);
+	ClosePhysicalChunk(iHwChunkOUT);
+
+	iValidInterface = EFalse;
+	}
+
+
+void DLddUsbcChannel::DestroyInterface(TUint aInterfaceNumber)
+	{
+	if (iAlternateSetting == aInterfaceNumber)
+		{
+		ResetInterface(KErrUsbInterfaceNotReady);
+		iValidInterface = EFalse;
+		iNumberOfEndpoints = 0;
+		for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
+			{
+			iEndpoint[i] = NULL;
+			}
+		}
+	TUsbcAlternateSettingList* alternateSettingListRec = iAlternateSettingList;
+	TUsbcAlternateSettingList* alternateSettingListRecOld = NULL;
+	while (alternateSettingListRec)
+		{
+		TUsbcAlternateSettingList* alternateSettingListRecNext = alternateSettingListRec->iNext;
+		if (alternateSettingListRec->iSetting == aInterfaceNumber)
+			{
+			// This record is to be deleted
+			if (alternateSettingListRecOld == NULL)
+				{
+				// The record to be deleted is at the list head
+				iAlternateSettingList = alternateSettingListRecNext;
+				}
+			else
+				{
+				// The record to be deleted is NOT at the list head
+				alternateSettingListRecOld->iNext = alternateSettingListRecNext;
+				}
+			delete alternateSettingListRec;
+			break;
+			}
+		alternateSettingListRecOld = alternateSettingListRec;
+		alternateSettingListRec = alternateSettingListRecNext;
+		}
+
+	if (iAlternateSettingList == NULL)
+		{
+		// if no interfaces left destroy non-ep0 buffering
+		ClosePhysicalChunk(iHwChunkIN);
+		ClosePhysicalChunk(iHwChunkOUT);
+		}
+	}
+
+
+void DLddUsbcChannel::DestroyEp0()
+	{
+	delete iEndpoint[0];
+	iEndpoint[0] = NULL;
+	ClosePhysicalChunk(iHwChunkEp0);
+	}
+
+
+void DLddUsbcChannel::EndpointStatusChangeCallback(TAny* aDLddUsbcChannel)
+    {
+	__KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback"));
+    DLddUsbcChannel* dUsbc = (DLddUsbcChannel*) aDLddUsbcChannel;
+	if (dUsbc->iChannelClosing)
+		return;
+	TUint endpointState = dUsbc->iEndpointStatusCallbackInfo.State();
+	const TInt reqNo = (TInt) RDevUsbcClient::ERequestEndpointStatusNotify;
+	if (dUsbc->iRequestStatus[reqNo])
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("EndpointStatusChangeCallback Notify status"));
+		DThread* client = dUsbc->iClient;
+		
+		dUsbc->iEndpointStatusChangeReq->Data() = endpointState;
+		dUsbc->iRequestStatus[reqNo] = NULL;
+		Kern::QueueRequestComplete(client,dUsbc->iEndpointStatusChangeReq,KErrNone);
+		dUsbc->iEndpointStatusChangePtr = NULL;
+		}
+	}
+
+
+void DLddUsbcChannel::StatusChangeCallback(TAny* aDLddUsbcChannel)
+	{
+    DLddUsbcChannel* dUsbc = (DLddUsbcChannel*) aDLddUsbcChannel;
+	if (dUsbc->iChannelClosing)
+		return;
+
+    TUsbcDeviceState deviceState;
+    TInt i;
+ 	for (i = 0;
+ 		 (i < KUsbcDeviceStateRequests) && ((deviceState = dUsbc->iStatusCallbackInfo.State(i)) != EUsbcNoState);
+ 		 ++i)
+		{
+ 		__KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallBack status=%d", deviceState));
+		if (deviceState & KUsbAlternateSetting)
+			{
+			dUsbc->ProcessAlternateSetting(deviceState);
+			}
+		else
+			{
+			dUsbc->ProcessDeviceState(deviceState);
+			}
+		// Only queue if userside is interested
+		if (dUsbc->iDeviceStatusNeeded)
+			{
+			dUsbc->iStatusFifo->AddStatusToQueue(deviceState);
+			const TInt reqNo = (TInt) RDevUsbcClient::ERequestAlternateDeviceStatusNotify;
+			if (dUsbc->AlternateDeviceStateTestComplete())
+				{
+					dUsbc->iRequestStatus[reqNo]=NULL;
+					Kern::QueueRequestComplete(dUsbc->iClient,dUsbc->iStatusChangeReq,KErrNone);
+				}
+			}
+		}
+ 	// We don't want to be interrupted in the middle of this:
+	const TInt irqs = NKern::DisableInterrupts(2);
+ 	dUsbc->iStatusCallbackInfo.ResetState();
+	NKern::RestoreInterrupts(irqs);
+	}
+
+
+void DLddUsbcChannel::OtgFeatureChangeCallback(TAny* aDLddUsbcChannel)
+    {
+	__KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback"));
+    DLddUsbcChannel* dUsbc = (DLddUsbcChannel*) aDLddUsbcChannel;
+	if (dUsbc->iChannelClosing)
+		return;
+
+    TUint8 features;
+    // No return value check. Assume OTG always supported here
+    dUsbc->iController->GetCurrentOtgFeatures(features);
+
+    const TInt reqNo = (TInt) RDevUsbcClient::ERequestOtgFeaturesNotify;
+	if (dUsbc->iRequestStatus[reqNo])
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("OtgFeatureChangeCallback Notify status"));
+		dUsbc->iOtgFeatureChangeReq->Data()=features;
+		dUsbc->iRequestStatus[reqNo] = NULL;
+		Kern::QueueRequestComplete(dUsbc->iClient,dUsbc->iOtgFeatureChangeReq,KErrNone);
+		dUsbc->iOtgFeatureChangePtr = NULL;
+		}
+    }
+
+
+TInt DLddUsbcChannel::SelectAlternateSetting(TUint aAlternateSetting)
+	{
+	TInt r = KErrGeneral;									// error code doesn't go userside
+	TUsbcAlternateSettingList* alternateSettingListRec = iAlternateSettingList;
+	while (alternateSettingListRec)
+		{
+		if (alternateSettingListRec->iSetting == aAlternateSetting)
+			{
+			// found the correct interface, now latch in new endpoint set
+			for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
+				{
+				iEndpoint[i] = NULL;
+				}
+			iNumberOfEndpoints = alternateSettingListRec->iNumberOfEndpoints;
+			r = KErrNone;
+			for (TInt i = 1; i <= KMaxEndpointsPerClient; i++)
+				{
+				iEndpoint[i] = alternateSettingListRec->iEndpoint[i];
+				}
+			// Only after correct alternate setting has been chosen.
+			UpdateEndpointSizes();
+			}
+		alternateSettingListRec = alternateSettingListRec->iNext;
+		}
+	return r;
+	}
+
+
+TInt DLddUsbcChannel::EpFromAlternateSetting(TUint aAlternateSetting, TInt aEndpoint)
+	{
+	TUsbcAlternateSettingList* alternateSettingListRec = iAlternateSettingList;
+	while (alternateSettingListRec)
+		{
+		if (alternateSettingListRec->iSetting == aAlternateSetting)
+			{
+			if ((aEndpoint <= alternateSettingListRec->iNumberOfEndpoints) &&
+				(aEndpoint >= 0))
+				{
+				return alternateSettingListRec->iEndpoint[aEndpoint]->RealEpNumber();
+				}
+			else
+				{
+				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: aEndpoint %d wrong for aAlternateSetting %d",
+												  aEndpoint, aAlternateSetting));
+				return -1;
+				}
+			}
+		alternateSettingListRec = alternateSettingListRec->iNext;
+		}
+	__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no aAlternateSetting %d found", aAlternateSetting));
+	return -1;
+	}
+
+
+TInt DLddUsbcChannel::ProcessAlternateSetting(TUint aAlternateSetting)
+	{
+	ResetInterface(KErrUsbInterfaceChange);					// kill any outstanding transfers
+	__KTRACE_OPT(KUSB, Kern::Printf("ProcessAlternateSetting 0x%08x", aAlternateSetting));
+	TUint newSetting = aAlternateSetting&(~KUsbAlternateSetting);
+	__KTRACE_OPT(KUSB, Kern::Printf("ProcessAlternateSetting selecting alternate setting 0x%08x", newSetting));
+	TInt r = SelectAlternateSetting(newSetting);
+	if (r != KErrNone)
+		return r;
+	StartEpReads();
+	iAlternateSetting = newSetting;
+    return KErrNone;
+	}
+
+
+TInt DLddUsbcChannel::ProcessDeviceState(TUsbcDeviceState aDeviceState)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("ProcessDeviceState(%d -> %d)", iDeviceState, aDeviceState));
+	if (iDeviceState == aDeviceState)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("  No state change => nothing to be done."));
+		return KErrNone;
+		}
+	if (iDeviceState == EUsbcDeviceStateSuspended)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("  Coming out of Suspend: old state = %d", iOldDeviceState));
+		iDeviceState = iOldDeviceState;
+		if (iDeviceState == aDeviceState)
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("  New state same as before Suspend => nothing to be done."));
+			return KErrNone;
+			}
+		}
+	TBool renumerateState = (aDeviceState == EUsbcDeviceStateConfigured);
+	TBool deconfigured = EFalse;
+	TInt cancellationCode = KErrNone;
+	if (aDeviceState == EUsbcDeviceStateSuspended)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("  Suspending..."));
+		iOldDeviceState = iDeviceState;
+		// Put PSL into low power mode here
+		}
+	else
+		{
+		deconfigured = (iDeviceState == EUsbcDeviceStateConfigured &&
+						aDeviceState != EUsbcDeviceStateConfigured);
+		if (iDeviceState == EUsbcDeviceStateConfigured)
+			{
+			if (aDeviceState == EUsbcDeviceStateUndefined)
+				cancellationCode = KErrUsbCableDetached;
+			else if (aDeviceState == EUsbcDeviceStateAddress)
+				cancellationCode = KErrUsbDeviceNotConfigured;
+			else if (aDeviceState == EUsbcDeviceStateDefault)
+				cancellationCode = KErrUsbDeviceBusReset;
+			else
+				cancellationCode = KErrUsbDeviceNotConfigured;
+			}
+		}
+	__KTRACE_OPT(KUSB, Kern::Printf("  %d --> %d", iDeviceState, aDeviceState));
+	iDeviceState = aDeviceState;
+	if (iValidInterface || iOwnsDeviceControl)
+		{
+		// This LDD may not own an interface. It could be some manager reenumerating
+		// after its subordinate LDDs have setup their interfaces.
+		if (deconfigured)
+			{
+		    DeConfigure(cancellationCode);
+			}
+		else if (renumerateState)
+			{
+			// Update size of Ep0.
+			iEndpoint[0]->SetMaxPacketSize(iController->Ep0PacketSize());
+			// First cancel transfers on all endpoints
+			ResetInterface(KErrUsbInterfaceChange);
+			// Select main interface & latch in new endpoint set
+			SelectAlternateSetting(0);
+			// Here we go
+			StartEpReads();
+			}
+		}
+
+	const TInt reqNo = (TInt) RDevUsbcClient::ERequestReEnumerate;
+	if (renumerateState && iRequestStatus[reqNo])
+		{
+		// This lot must be done if we are reenumerated
+		CompleteBufferRequest(iClient, reqNo, KErrNone);
+		}
+
+    return KErrNone;
+    }
+
+
+void DLddUsbcChannel::UpdateEndpointSizes()
+	{
+	// The regular ones.
+	TInt i = 0;
+	while ((++i <= KMaxEndpointsPerClient) && iEndpoint[i])
+		{
+		const TInt size = iController->EndpointPacketSize(this, iEndpoint[i]->RealEpNumber());
+		if (size < 0)
+			{
+			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Packet size < 0 for ep %d", i));
+			continue;
+			}
+		iEndpoint[i]->SetMaxPacketSize(size);
+		}
+	__ASSERT_DEBUG(i == iNumberOfEndpoints + 1,
+				   Kern::Printf("  Error: iNumberOfEndpoints wrong (%d)", iNumberOfEndpoints));
+	}
+
+
+DPlatChunkHw* DLddUsbcChannel::ReAllocate(TInt aBuffersize, DPlatChunkHw* aHwChunk, TUint32 aCacheAttribs)
+	{
+	DPlatChunkHw* chunk = aHwChunk;
+	if ((!chunk) || (chunk->iSize < aBuffersize))
+		{
+		if (chunk)
+			{
+			ClosePhysicalChunk(chunk);
+			}
+		__KTRACE_OPT(KUSB, Kern::Printf("ReAllocate need to get new chunk"));
+		chunk = Allocate(aBuffersize, aCacheAttribs);
+		}
+	return chunk;
+	}
+
+
+DPlatChunkHw* DLddUsbcChannel::Allocate(TInt aBuffersize, TUint32 aCacheAttribs)
+	{
+	TUint32 physAddr = 0;
+	TUint32 size = Kern::RoundToPageSize(aBuffersize);
+
+	if (Epoc::AllocPhysicalRam(size, physAddr) != KErrNone)
+		return NULL;
+
+	DPlatChunkHw* HwChunk;
+	if (DPlatChunkHw::New(HwChunk, physAddr, aBuffersize, aCacheAttribs) != KErrNone)
+		{
+		Epoc::FreePhysicalRam(physAddr, size);
+		return NULL;
+		}
+
+	return HwChunk;
+	}
+
+
+TInt DLddUsbcChannel::DoRxComplete(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint, TBool aReEntrant)
+	{
+	TBool completeNow;
+	TInt err = aTUsbcEndpoint->CopyToClient(iClient, completeNow,iClientAsynchNotify[aEndpoint]->iClientBuffer);
+	if (completeNow)
+		{
+		aTUsbcEndpoint->SetClientReadPending(EFalse);
+		CompleteBufferRequest(iClient, aEndpoint, err);
+		}
+	aTUsbcEndpoint->TryToStartRead(aReEntrant);
+	return err;
+	}
+
+
+void DLddUsbcChannel::DoRxCompleteNow(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint)
+	{
+	aTUsbcEndpoint->SetClientReadPending(EFalse);
+	CompleteBufferRequest(iClient, aEndpoint, KErrCancel);
+	}
+
+
+void DLddUsbcChannel::DoTxComplete(TUsbcEndpoint* aTUsbcEndpoint, TInt aEndpoint, TInt aError)
+	{
+	aTUsbcEndpoint->SetClientWritePending(EFalse);
+	CompleteBufferRequest(iClient, aEndpoint, aError);
+	}
+
+
+TBool DLddUsbcChannel::AlternateDeviceStateTestComplete()
+	{
+	TBool completeNow = EFalse;
+	const TInt reqNo = (TInt) RDevUsbcClient::ERequestAlternateDeviceStatusNotify;
+	if (iRequestStatus[reqNo])
+		{
+		// User req is outstanding
+		TUint32 deviceState;
+		if (iStatusFifo->GetDeviceQueuedStatus(deviceState) == KErrNone)
+			{
+			// Device state waiting to be sent userside
+			completeNow = ETrue;
+			__KTRACE_OPT(KUSB, Kern::Printf("StatusChangeCallback Notify status"));
+			iStatusChangeReq->Data()=deviceState;
+			iStatusChangePtr = NULL;
+			}
+		}
+	return completeNow;
+	}
+
+
+void DLddUsbcChannel::EmergencyCompleteDfc(TAny* aDLddUsbcChannel)
+	{
+	((DLddUsbcChannel*) aDLddUsbcChannel)->DoEmergencyComplete();
+	}
+
+
+void DLddUsbcChannel::DeConfigure(TInt aErrorCode)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcChannel::DeConfigure()"));
+	// Called after deconfiguration. Cancels transfers on all endpoints.
+	ResetInterface(aErrorCode);
+	// Cancel the endpoint status notify request if it is outstanding.
+	const TInt KEpNotReq = RDevUsbcClient::ERequestEndpointStatusNotify;
+	if (iRequestStatus[KEpNotReq])
+		{
+		CancelNotifyEndpointStatus();
+		iRequestStatus[KEpNotReq]=NULL;
+		Kern::QueueRequestComplete(iClient,iEndpointStatusChangeReq,aErrorCode);
+		}
+	// We have to reset the alternate setting number when the config goes away.
+ 	SelectAlternateSetting(0);
+	iAlternateSetting = 0;
+	}
+
+
+void DLddUsbcChannel::StartEpReads()
+	{
+	// Queued after enumeration. Starts reads on all endpoints.
+	// The endpoint itself decides if it can do a read
+	TInt i;
+	for (i = 0; i <= iNumberOfEndpoints; i++)
+		{
+		// The endpoint itself will decide if it can read
+		iEndpoint[i]->TryToStartRead(EFalse);
+		}
+	}
+
+
+void DLddUsbcChannel::ResetInterface(TInt aErrorCode)
+	{
+	// Called after change in alternate setting.  Cancels transfers on all endpoints
+	if (iValidInterface || iOwnsDeviceControl)
+		{
+		// Reset each endpoint except ep0
+		for (TInt i = 1; i <= iNumberOfEndpoints; i++)
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("Cancelling transfer ep=%d", i));
+			iEndpoint[i]->CancelTransfer(iClient,iClientAsynchNotify[i]->iClientBuffer);			// Copies data userside
+			iEndpoint[i]->AbortTransfer();					// kills any ldd->pil outstanding transfers
+			iEndpoint[i]->iDmaBuffers->Flush();
+			if (iRequestStatus[i] != NULL)
+				CompleteBufferRequest(iClient, i, aErrorCode);
+			iEndpoint[i]->SetClientWritePending(EFalse);
+			iEndpoint[i]->SetClientReadPending(EFalse);
+			}
+		}
+	}
+
+
+void DLddUsbcChannel::AbortInterface()
+	{
+	// Called after when channel is closing
+	if (iValidInterface || iOwnsDeviceControl)
+		{
+		for (TInt i = 0; i <= iNumberOfEndpoints; i++)
+			{
+			if (iEndpoint[i])
+				{
+				// kills any LDD->PDD outstanding transfers
+				iEndpoint[i]->AbortTransfer();
+				}
+			}
+		}
+	}
+
+
+void DLddUsbcChannel::ClosePhysicalChunk(DPlatChunkHw*& aHwChunk)
+	{
+	if (aHwChunk)
+		{
+ 		const TPhysAddr addr = aHwChunk->PhysicalAddress();
+ 		const TInt size = aHwChunk->iSize;
+		aHwChunk->Close(NULL);
+ 		Epoc::FreePhysicalRam(addr, size);
+		}
+	aHwChunk = NULL;
+	}
+
+
+TInt DLddUsbcChannel::DoEmergencyComplete()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::DoEmergencyComplete"));
+	// cancel any pending DFCs
+	// complete all client requests
+    for (TInt i = 0; i < KUsbcMaxRequests; i++)
+        {
+        if (iRequestStatus[i])
+            {
+            __KTRACE_OPT(KUSB, Kern::Printf("Complete request 0x%x", iRequestStatus[i]));
+		CompleteBufferRequest(iClient, i, KErrDisconnected);
+            }
+        }
+    iStatusCallbackInfo.Cancel();
+    iEndpointStatusCallbackInfo.Cancel();
+    iOtgFeatureCallbackInfo.Cancel();
+	return KErrNone;
+	}
+
+
+void DLddUsbcChannel::PanicClientThread(TInt aReason)
+	{
+	Kern::ThreadKill(iClient, EExitPanic, aReason, KUsbLDDKillCat);
+	}
+
+
+// ===============Endpoint====================
+
+// Constructor
+TUsbcEndpoint::TUsbcEndpoint(DLddUsbcChannel* aLDD, DUsbClientController* aController,
+							 const TUsbcEndpointInfo* aEndpointInfo, TInt aEndpointNum,
+							 TInt aBandwidthPriority)
+	: iController(aController),
+	  iEndpointInfo(aEndpointInfo->iType, aEndpointInfo->iDir, aEndpointInfo->iSize),
+	  iClientReadPending(EFalse),
+	  iClientWritePending(EFalse),
+	  iEndpointNumber(aEndpointNum),
+	  iRealEpNumber(-1),
+	  iLdd(aLDD),
+	  iError(KErrNone),
+	  iRequestCallbackInfo(NULL),
+	  iBytesTransferred(0),
+	  iBandwidthPriority(aBandwidthPriority)
+	{
+ 	ResetTransferInfo();
+	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::TUsbcEndpoint 2"));
+	}
+
+
+TInt TUsbcEndpoint::Construct()
+	{
+	iDmaBuffers = new TDmaBuf(&iEndpointInfo, iBandwidthPriority);
+	if (iDmaBuffers == NULL)
+		{
+		return KErrNoMemory;
+		}
+	const TInt r = iDmaBuffers->Construct(&iEndpointInfo);
+	if (r != KErrNone)
+		{
+		return r;
+		}
+	iRequestCallbackInfo = new TUsbcRequestCallback(iLdd,
+													iEndpointNumber,
+													TUsbcEndpoint::RequestCallback,
+													this,
+													iLdd->iDfcQ,
+													KUsbRequestCallbackPriority);
+	if (iRequestCallbackInfo == NULL)
+		{
+		return KErrNoMemory;
+		}
+	return KErrNone;
+	}
+
+
+TUsbcEndpoint::~TUsbcEndpoint()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::~TUsbcEndpoint(%d)", iEndpointNumber));
+	AbortTransfer();
+	delete iRequestCallbackInfo;
+	delete iDmaBuffers;
+	}
+
+
+void TUsbcEndpoint::RequestCallback(TAny* aTUsbcEndpoint)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::RequestCallback"));
+	((TUsbcEndpoint*) aTUsbcEndpoint)->EndpointComplete();
+	}
+
+
+void TUsbcEndpoint::SetMaxPacketSize(TInt aSize)
+	{
+	iEndpointInfo.iSize = aSize;
+	iDmaBuffers->SetMaxPacketSize(aSize);
+	}
+
+
+TInt TUsbcEndpoint::EndpointComplete()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::EndpointComplete ep=%d %d",
+									iEndpointNumber, iRequestCallbackInfo->iEndpointNum));
+
+	if (iLdd->ChannelClosing())
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("We're going home -> completions no longer accepted"));
+		return KErrNone;
+		}
+
+	TTransferDirection transferDir = iRequestCallbackInfo->iTransferDir;
+	TInt error = iRequestCallbackInfo->iError;
+
+	switch (transferDir)
+		{
+
+	case EControllerWrite:
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::EndpointComplete Write 2"));
+		if (!iDmaBuffers->TxIsActive())
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("  TX completion but !iDmaBuffers->TxIsActive()"));
+			break;
+			}
+
+		iDmaBuffers->TxSetInActive();
+		TBool completeNow = EFalse;
+		iBytesTransferred += iRequestCallbackInfo->iTxBytes;
+		if (iClientWritePending)
+			{
+			//Complete Outstanding Write if necessary
+			iError = error;
+			if (iError != KErrNone)
+				{
+				completeNow = ETrue;
+				if (iError == KErrPrematureEnd)				// Previous write could not be completed
+					iError = KErrNone;
+				}
+			else
+				{
+				if (iBytesTransferred == (TUint32) iTransferInfo.iTransferSize)
+					{
+					completeNow = ETrue;
+					}
+				else
+					{
+					iError = ContinueWrite();
+					if (iError != KErrNone)
+						completeNow = ETrue;
+					}
+				}
+			if (completeNow)
+				{
+				TxComplete();
+				ResetTransferInfo();
+				if (iEndpointNumber == 0)
+					{
+					iDmaBuffers->Flush();
+					TryToStartRead(EFalse);
+					}
+				}
+			}
+		break;
+		}
+
+	case EControllerRead:
+		{
+		// The first packet always contains the total #of bytes
+		const TInt byteCount = iRequestCallbackInfo->iPacketSize[0];
+		const TInt packetCount = iRequestCallbackInfo->iRxPackets;
+		iDmaBuffers->ReadXferComplete(byteCount, packetCount, error);
+
+		// We queue the dfc if we can complete the read, i.e. if we are reading a packet,
+		// or if we have enough data to satisfy a read data request.
+		if (iClientReadPending)
+			{
+			//Complete outstanding read
+			__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpoint::EndpointComplete Read 3 (bytes "
+											"available=%d)", iDmaBuffers->RxBytesAvailable()));
+			TInt bytesReqd = iTransferInfo.iTransferSize - iBytesTransferred;
+			TBool completeNow = EFalse;
+
+			if (iTransferInfo.iTransferType == ETransferTypeReadPacket ||
+				iTransferInfo.iTransferType == ETransferTypeReadOneOrMore)
+				{
+				// Always complete on a packet read
+				completeNow = ETrue;
+				}
+			else if (iTransferInfo.iTransferType == ETransferTypeReadData)
+				{
+				// Complete only if enough data is present
+				if (iDmaBuffers->RxBytesAvailable() >= bytesReqd)
+					completeNow = ETrue;
+				}
+			else if (iTransferInfo.iTransferType == ETransferTypeReadUntilShort)
+				{
+				// Complete if enough data is present or if a short packet has been delivered
+				const TInt maxPacketSize = iEndpointInfo.iSize;
+				const TInt lastPacketSize = iRequestCallbackInfo->iPacketSize[packetCount - 1];
+				if (lastPacketSize < maxPacketSize)
+					completeNow = ETrue;
+				else if (iDmaBuffers->RxBytesAvailable() >= bytesReqd)
+					completeNow = ETrue;
+				else
+					{
+					const TUint type = iEndpointInfo.iType;
+					if ((type == KUsbEpTypeBulk) && (lastPacketSize & (maxPacketSize - 1)))
+						{
+						completeNow = ETrue;
+						}
+					else if ((type != KUsbEpTypeBulk) &&
+							 (lastPacketSize > maxPacketSize) &&
+							 (lastPacketSize % maxPacketSize))
+						{
+						completeNow = ETrue;
+						}
+					}
+				}
+			if (completeNow)
+				{
+				iError = error;
+				RxComplete(EFalse);
+				iClientReadPending = EFalse;
+				}
+			}
+		iDmaBuffers->RxSetInActive();
+		if (error != KErrNone)
+			{
+			return error;
+			}
+		if (TryToStartRead(EFalse) != KErrNone)
+			{
+//			if (iEndpointNumber != 0)
+//				Kern::Printf("EndpointComplete couldn't start read on ep=%d", iEndpointNumber);
+			}
+		break;
+		}
+
+	default:
+		// shouldn't get here
+		break;
+		}
+
+	return KErrNone;
+	}
+
+
+void TUsbcEndpoint::TxComplete()
+	{
+	iLdd->DoTxComplete(this, iEndpointNumber, iError);
+	}
+
+
+TInt TUsbcEndpoint::RxComplete(TBool aReEntrant)
+	{
+	return iLdd->DoRxComplete(this, iEndpointNumber, aReEntrant);
+	}
+
+
+void TUsbcEndpoint::RxCompleteNow()
+	{
+	iLdd->DoRxCompleteNow(this, iEndpointNumber);
+	}
+
+
+TInt TUsbcEndpoint::CopyToClient(DThread* aClient, TClientBuffer *aTcb)
+	{
+	TBool completeNow;
+	return CopyToClient(aClient, completeNow,aTcb);
+	}
+
+
+TInt TUsbcEndpoint::CopyToClient(DThread* aClient, TBool& aCompleteNow, TClientBuffer *aTcb)
+	{
+	TInt err;
+	const TInt length = iTransferInfo.iTransferSize;
+	const TBool KReadData = EFalse;
+	const TBool KReadUntilShort = ETrue;
+
+	__KTRACE_OPT(KUSB, Kern::Printf("CopyToClient: length = %d", length));
+
+	if (iTransferInfo.iTransferType == ETransferTypeReadPacket)
+		{
+		err = iDmaBuffers->RxCopyPacketToClient(aClient, aTcb, length);
+		aCompleteNow = ETrue;
+		}
+	else if (iTransferInfo.iTransferType == ETransferTypeReadOneOrMore)
+		{
+		err = iDmaBuffers->RxCopyDataToClient(aClient, aTcb, length, iBytesTransferred,
+											  KReadData, aCompleteNow);
+		aCompleteNow = ETrue;
+		}
+	else if (iTransferInfo.iTransferType == ETransferTypeReadUntilShort)
+		{
+		err = iDmaBuffers->RxCopyDataToClient(aClient, aTcb, length, iBytesTransferred,
+											  KReadUntilShort, aCompleteNow);
+		}
+	else
+		{
+		err = iDmaBuffers->RxCopyDataToClient(aClient, aTcb, length, iBytesTransferred,
+											  KReadData, aCompleteNow);
+		}
+
+	if (aCompleteNow)
+		{
+		ResetTransferInfo();
+		SetClientReadPending(EFalse);
+		}
+
+	return err;
+	}
+
+
+TInt TUsbcEndpoint::TryToStartRead(TBool aReEntrant)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("TryToStartRead 1 ep=%d", iEndpointNumber));
+	TInt r = KErrNone;
+	if (iEndpointInfo.iDir != KUsbEpDirOut &&
+		iEndpointInfo.iDir != KUsbEpDirBidirect)
+		{
+		// Verify ep direction
+		__KTRACE_OPT(KUSB, Kern::Printf("TryToStartRead wrong direction ep=%d", iEndpointNumber));
+		return KErrUsbEpBadDirection;
+		}
+
+	if (iEndpointNumber == 0)
+		{
+		// Can't issue an Ep0 read if reader or writer is active
+		if (iDmaBuffers->TxIsActive())
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("TryToStartRead ep0 Tx already active FATAL"));
+			return KErrUsbEpNotReady;
+			}
+		if (iDmaBuffers->RxIsActive())
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("TryToStartRead ep0 Rx already active non-FATAL"));
+			}
+		}
+
+	if (!(iDmaBuffers->RxIsActive()))
+		{
+		TUint8* bufferAddr;
+		TPhysAddr physAddr;
+		TUsbcPacketArray* indexArray;
+		TUsbcPacketArray* sizeArray;
+		TInt length;
+		r = iDmaBuffers->RxGetNextXfer(bufferAddr, indexArray, sizeArray, length, physAddr);
+		if (r == KErrNone)
+			{
+			iDmaBuffers->RxSetActive();
+			iRequestCallbackInfo->SetRxBufferInfo(bufferAddr, physAddr, indexArray, sizeArray, length);
+
+			__KTRACE_OPT(KUSB, Kern::Printf("TryToStartRead 2 bufferAddr=0x%08x", bufferAddr));
+
+			r = iController->SetupReadBuffer(*iRequestCallbackInfo);
+			if (r != KErrNone)
+				{
+				iDmaBuffers->RxSetInActive();
+				__KTRACE_OPT(KPANIC, Kern::Printf("  Error: TryToStartRead controller rejects read"));
+				}
+			}
+		else
+			{
+			if (iClientReadPending)
+				{
+				// Deadlock, try to resolve it by draining buffer into descriptor
+				if (!aReEntrant)
+					{
+					RxComplete(ETrue);
+					}
+				else
+					{
+					// we are stuck, better complete userside otherwise the userside request will hang
+					RxCompleteNow();
+					}
+				}
+			}
+		}
+	return r;
+	}
+
+
+TInt TUsbcEndpoint::TryToStartWrite(TEndpointTransferInfo* pTfr)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("TryToStartWrite 1 ep=%d", iEndpointNumber));
+	if (iEndpointInfo.iDir != KUsbEpDirIn &&
+		iEndpointInfo.iDir != KUsbEpDirBidirect)
+		{
+		// Verify ep direction
+		return KErrUsbEpBadDirection;
+		}
+	if (iEndpointNumber == 0)
+		{
+		// Can't issue an Ep0 write if unread data is available or writer is active
+		if (iDmaBuffers->TxIsActive() || !iDmaBuffers->IsReaderEmpty())
+			{
+			return KErrUsbEpNotReady;
+			}
+		if (iDmaBuffers->RxIsActive())
+			{
+			// if a reader is active then cancel the read
+			iDmaBuffers->RxSetInActive();
+			iController->CancelReadBuffer(iLdd, iRealEpNumber);
+			}
+		}
+	SetTransferInfo(pTfr);
+	ContinueWrite();
+	return KErrNone;
+	}
+
+
+TInt TUsbcEndpoint::ContinueWrite()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("ContinueWrite 2"));
+	TUint8* bufferAddr;
+	TPhysAddr physAddr;
+	TInt bufferLength;
+	TInt r = iDmaBuffers->TxGetNextXfer(bufferAddr, bufferLength, physAddr);
+	if (r != KErrNone)											// probably already active
+		return r;
+	__KTRACE_OPT(KUSB, Kern::Printf("ContinueWrite 3"));
+	iDmaBuffers->TxSetActive();
+	TBool zlpReqd = EFalse;
+	TUint32 transferSize = iTransferInfo.iTransferSize;
+	TInt length = Min(transferSize - iBytesTransferred, (TUint32) bufferLength);
+	if (iBytesTransferred+length>=transferSize)
+		{
+		// only send a zlp if this is the last buffer of the transfer
+		zlpReqd = iTransferInfo.iZlpReqd;
+		}
+	r = iDmaBuffers->TxStoreData(iLdd->Client(), iLdd->GetClientBuffer(iEndpointNumber), length, iBytesTransferred);
+	if (r != KErrNone)											
+		return r;
+	iDmaBuffers->TxSetActive();
+	iRequestCallbackInfo->SetTxBufferInfo(bufferAddr, physAddr, length);
+	iRequestCallbackInfo->iZlpReqd = zlpReqd;
+#if 0
+	for (TInt i = 0; i < iRequestCallbackInfo->iLength; i++)
+		{
+		__KTRACE_OPT(KUSB, Kern::Printf("Buffer[%d] = 0x%02x", i, iRequestCallbackInfo->iBufferStart[i]));
+		}
+#endif
+	r = iController->SetupWriteBuffer(*iRequestCallbackInfo);
+	return r;
+	}
+
+
+void TUsbcEndpoint::CancelTransfer(DThread* aThread, TClientBuffer *aTcb)
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("CancelTransfer"));
+	if (iDmaBuffers != NULL)
+		{
+		if (iClientWritePending)
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("  (iClientWritePending)"));
+			iClientWritePending = EFalse;
+			iController->CancelWriteBuffer(iLdd, iRealEpNumber);
+			iDmaBuffers->TxSetInActive();
+			}
+		if (iClientReadPending)
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("  (iClientReadPending)"));
+			iClientReadPending = EFalse;
+			CopyToClient(aThread,aTcb);
+			}
+		}
+	}
+
+
+void TUsbcEndpoint::AbortTransfer()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("Abort Transfer"));
+	if (iDmaBuffers != NULL)
+		{
+		if (iDmaBuffers->TxIsActive())
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("  (iClientWritePending)"));
+			iController->CancelWriteBuffer(iLdd, iRealEpNumber);
+			iDmaBuffers->TxSetInActive();
+			}
+		if (iDmaBuffers->RxIsActive())
+			{
+			__KTRACE_OPT(KUSB, Kern::Printf("  (iClientReadPending)"));
+			iController->CancelReadBuffer(iLdd, iRealEpNumber);
+			iDmaBuffers->RxSetInActive();
+			}
+		iRequestCallbackInfo->iDfc.Cancel();
+		}
+	}
+
+
+TUsbcAlternateSettingList::TUsbcAlternateSettingList()
+	: iNext(NULL),
+	  iNumberOfEndpoints(0),
+	  iSetting(0)
+	{
+	for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
+		{
+		iEndpoint[i] = NULL;
+		}
+	}
+
+
+TUsbcAlternateSettingList::~TUsbcAlternateSettingList()
+	{
+	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcAlternateSettingList::~TUsbcAlternateSettingList()"));
+	for (TInt i = 0; i <= KMaxEndpointsPerClient; i++)
+		{
+		delete iEndpoint[i];
+		}
+	}
+
+
+TUsbcDeviceStatusQueue::TUsbcDeviceStatusQueue()
+	{
+	FlushQueue();
+	}
+
+
+void TUsbcDeviceStatusQueue::FlushQueue()
+	{
+	for (TInt i = 0; i < KUsbDeviceStatusQueueDepth; i++)
+		{
+		iDeviceStatusQueue[i] = KUsbDeviceStatusNull;
+		}
+	iStatusQueueHead = 0;
+	}
+
+
+void TUsbcDeviceStatusQueue::AddStatusToQueue(TUint32 aDeviceStatus)
+	{
+	// Only add a new status if it is not a duplicate of the one at the head of the queue
+	if (!(iStatusQueueHead != 0 &&
+		  iDeviceStatusQueue[iStatusQueueHead - 1] == aDeviceStatus))
+		{
+		if (iStatusQueueHead == KUsbDeviceStatusQueueDepth)
+			{
+			// Discard item at tail of queue
+			TUint32 status;
+			GetDeviceQueuedStatus(status);
+			}
+		iDeviceStatusQueue[iStatusQueueHead] = aDeviceStatus;
+		iStatusQueueHead++;
+		}
+	}
+
+
+TInt TUsbcDeviceStatusQueue::GetDeviceQueuedStatus(TUint32& aDeviceStatus)
+	{
+	TInt r = KErrNone;
+	if (iStatusQueueHead <= 0)
+		{
+		r = KErrGeneral;
+		aDeviceStatus = KUsbDeviceStatusNull;
+		}
+	else
+		{
+		aDeviceStatus = iDeviceStatusQueue[0];
+		for(TInt i = 1; i < KUsbDeviceStatusQueueDepth; i++)
+			{
+			TUint32 s = iDeviceStatusQueue[i];
+			iDeviceStatusQueue[i - 1] = s;
+			}
+		iStatusQueueHead--;
+		iDeviceStatusQueue[KUsbDeviceStatusQueueDepth - 1] = KUsbDeviceStatusNull;
+		}
+	return r;
+	}
+
+void TClientAsynchNotify::Reset()
+{
+	iBufferRequest->Reset();
+	iClientBuffer=NULL;
+}
+
+//---