--- /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;
+}
+
+//---