diff -r f92a4f87e424 -r 012cc2ee6408 usbdrv/peripheral/ldd/perildd/src/d_usbc.cpp --- a/usbdrv/peripheral/ldd/perildd/src/d_usbc.cpp Tue Aug 31 17:01:47 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3233 +0,0 @@ -// 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 - - -_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 UsbShai::KUsbEpTypeControl: - if (dir != UsbShai::KUsbEpDirBidirect || size > 64) - return EFalse; - break; - case UsbShai::KUsbEpTypeIsochronous: - if ((dir != UsbShai::KUsbEpDirIn && dir != UsbShai::KUsbEpDirOut) || size > 1024) - return EFalse; - break; - case UsbShai::KUsbEpTypeBulk: - if ((dir != UsbShai::KUsbEpDirIn && dir != UsbShai::KUsbEpDirOut) || size > 512) - return EFalse; - break; - case UsbShai::KUsbEpTypeInterrupt: - if ((dir != UsbShai::KUsbEpDirIn && dir != UsbShai::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 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), - iNumberOfEndpoints(0), - iDeviceState(UsbShai::EUsbPeripheralStateUndefined), - 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) - { - iController->DeRegisterClient(this); - iStatusCallbackInfo.Cancel(); - iEndpointStatusCallbackInfo.Cancel(); - iOtgFeatureCallbackInfo.Cancel(); - iCompleteAllCallbackInfo.Cancel(); - AbortInterface(); - DestroyAllInterfaces(); - if (iOwnsDeviceControl) - { - iController->ReleaseDeviceControl(this); - iOwnsDeviceControl = EFalse; - } - 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 == UsbShai::EUsbPeripheralStateConfigured || - iDeviceState == UsbShai::EUsbPeripheralStateSuspended)) - ) - { - __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 != UsbShai::KUsbEpDirOut && - pEndpointInfo->iDir != UsbShai::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 != UsbShai::KUsbEpDirIn && - pEndpointInfo->iDir != UsbShai::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 == UsbShai::EUsbPeripheralStateConfigured)) - { - iController->Ep0Stall(this); - } - else - { - if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured) - r = KErrUsbDeviceNotConfigured; - else - r = KErrUsbInterfaceNotReady; - } - break; - - case RDevUsbcClient::EControlGetAlternateSetting: - __KTRACE_OPT(KUSB, Kern::Printf("EControlGetAlternateSetting")); - if (iValidInterface && iDeviceState == UsbShai::EUsbPeripheralStateConfigured) - { - r = iController->GetInterfaceNumber(this, *(TInt*)a1); - } - else - { - if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured) - 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 != UsbShai::EUsbPeripheralStateConfigured) - 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 != UsbShai::KUsbEpDirIn) - { - __KTRACE_OPT(KUSB, Kern::Printf(" bytes = %d", pEndpoint->RxBytesAvailable())); - *(TInt*)a2 = pEndpoint->RxBytesAvailable(); - } - } - else - { - if (iDeviceState != UsbShai::EUsbPeripheralStateConfigured) - 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 != UsbShai::EUsbPeripheralStateConfigured) - 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 != UsbShai::EUsbPeripheralStateConfigured) - 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(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 == UsbShai::EUsbPeripheralStateConfigured)) - { - 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(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(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(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::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; - - // Supports ep0+5 endpoints - 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; - } - - __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcChannel::SetInterface num_endpoints=%d", num_endpoints)); - - // other endpoints - // calculate the total buffer size - 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; - } - - __KTRACE_OPT(KUSB, Kern::Printf("SetInterface for ep=%d rec=0x%08x ep==0x%08x", - i, alternateSettingListRec, ep)); - } - - // buf size of each endpoint - TInt bufSizes[KMaxEndpointsPerClient + 1]; - TInt epNum[KMaxEndpointsPerClient + 1]; - - // init - for( TInt i=0;iiEndpoint[i]->BufferSize(); - } - - __KTRACE_OPT(KUSB, Kern::Printf("Sort the endpoints:")); - - // sort the endpoint number by the bufsize decreasely - for( TInt i=1;iiEpNumDeOrderedByBufSize[i] = epNum[i]; - - __KTRACE_OPT(KUSB, Kern::Printf(" %d:%d", epNum[i], bufSizes[i])); - } - alternateSettingListRec->iEpNumDeOrderedByBufSize[num_endpoints] = epNum[num_endpoints]; - __KTRACE_OPT(KUSB, Kern::Printf(" %d:%d", epNum[num_endpoints], bufSizes[num_endpoints])); - __KTRACE_OPT(KUSB, Kern::Printf("\n")); - - // 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]); - } - - r = SetupInterfaceMemory(iHwChunks, cacheAttribs ); - if( r==KErrNone ) - { - __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; - } - else - { - __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; - } - -// realloc the memory, and set the previous interfaces -TInt DLddUsbcChannel::SetupInterfaceMemory(RArray &aHwChunks, - TUint32 aCacheAttribs ) - { - TUsbcAlternateSettingList* asRec = iAlternateSettingList; - - // if buffers has been changed - TBool chunkChanged = EFalse; - TInt numOfEp = asRec->iNumberOfEndpoints; - - // 1, collect all bufs' sizes for the current interface - // to realloc all the chunks - __KTRACE_OPT(KUSB, Kern::Printf("Collect all buffer sizes:")); - RArray bufSizes; - for(TInt i=1;i<=numOfEp;i++) - { - TInt nextEp = asRec->iEpNumDeOrderedByBufSize[i]; - TInt epBufCount = asRec->iEndpoint[nextEp]->BufferNumber(); - __KTRACE_OPT(KUSB, Kern::Printf(" ep %d, buf count %d", nextEp, epBufCount )); - for(TInt k=0;kiEndpoint[nextEp]->BufferSize(); - TInt r = bufSizes.Append(epBufSize); - if(r!=KErrNone) - { - iController->DeRegisterClient(this); - bufSizes.Close(); - return r; - } - __KTRACE_OPT(KUSB,Kern::Printf(" %d", epBufSize )); - } - __KTRACE_OPT(KUSB, Kern::Printf("\n")); - - } - - // 2, alloc the buffer decreasely, biggest-->smallest - // 2.1 check the existing chunks - TInt bufCount = bufSizes.Count(); - __KTRACE_OPT(KUSB, Kern::Printf(" ep buf number needed %d", bufCount )); - __KTRACE_OPT(KUSB, Kern::Printf(" chunks available %d", aHwChunks.Count() )); - - TInt chunkInd = 0; - while( (chunkInd(aHwChunks[chunkInd]->LinearAddress()); - - DPlatChunkHw* chunk = ReAllocate(bufSizes[chunkInd], aHwChunks[chunkInd], aCacheAttribs); - if (chunk == NULL) - { - __KTRACE_OPT(KUSB, Kern::Printf("Failed to alloc chunks size %d!", bufSizes[chunkInd])); - // lost all interfaces: - // Tell Controller to release Interface and h/w resources associated with this - iController->DeRegisterClient(this); - bufSizes.Close(); - return KErrNoMemory; - } - else - { - // Parcel out the memory between endpoints - TUint8* newAddr = reinterpret_cast(chunk->LinearAddress()); - __KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory alloc new chunk=0x%x, size=%d", newAddr,bufSizes[chunkInd])); - // The check is important to avoid chunkChanged to be corrupted. - // This code change is to fix the problem that one chunk is used by multiple interfaces. - if(!chunkChanged) - { - chunkChanged = (newAddr != oldAddr); - } - aHwChunks[chunkInd] = chunk; - } - chunkInd++; - } - - // 2.2 in case available chunks are not enough - while( chunkIndDeRegisterClient(this); - bufSizes.Close(); - return KErrNoMemory; - } - else - { - // Parcel out the memory between endpoints - __KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory alloc new chunk=0x%x, size=%d", - reinterpret_cast(chunk->LinearAddress()), bufSizes[chunkInd])); - TInt r = aHwChunks.Append(chunk); - if(r!=KErrNone) - { - ClosePhysicalChunk(chunk); - iController->DeRegisterClient(this); - bufSizes.Close(); - return r; - } - } - chunkInd++; - } - - // 3, Set the the bufs of the interfaces - - ReSetInterfaceMemory(asRec, aHwChunks); - - if(chunkChanged) - { - __KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory readdressing.")); - 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 readdressing setting=%d", asRec->iSetting)); - ReSetInterfaceMemory(asRec, aHwChunks); - asRec = asRec->iNext; - } - } - return KErrNone; - } - -TInt DLddUsbcChannel::SetupEp0() - { - __KTRACE_OPT(KUSB, Kern::Printf("SetupEp0 entry %x", this)); - TInt ep0Size = iController->Ep0PacketSize(); - TUsbcEndpointInfo ep0Info = TUsbcEndpointInfo(UsbShai::KUsbEpTypeControl, UsbShai::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 bufferNum = ep0->BufferNumber(); - TInt bufferSize = ep0->BufferSize(); - TUint32 cacheAttribs = EMapAttrSupRw | EMapAttrCachedMax; - - for(TInt i=0;iLinearAddress(); - ep0->SetBufferAddr( i, buf); - __KTRACE_OPT(KUSB, Kern::Printf("SetupEp0 60 buffer number %d", i)); - __KTRACE_OPT(KUSB, Kern::Printf("SetupEp0 60 buffer size %d", bufferSize)); - } - - ep0->SetRealEpNumber(0); - return KErrNone; - } - -// Set buffer address of the interface -// Precondition: Enough chunks available. -void DLddUsbcChannel::ReSetInterfaceMemory(TUsbcAlternateSettingList* aAlternateSettingListRec, - RArray &aHwChunks) - { - TUsbcAlternateSettingList* asRec = aAlternateSettingListRec; - - // set all the interfaces - TInt chunkInd = 0; - TInt numOfEp = asRec->iNumberOfEndpoints; - - for (TInt i = 1; i <= numOfEp; i++) - { - TInt nextEp = asRec->iEpNumDeOrderedByBufSize[i]; - TInt epBufCount = asRec->iEndpoint[nextEp]->BufferNumber(); - for(TInt k=0;kiEndpoint[nextEp]; - if (ep != NULL ) - { - TUint8* pBuf = NULL; - pBuf = reinterpret_cast(aHwChunks[chunkInd]->LinearAddress()); - ep->SetBufferAddr( k, pBuf); - __KTRACE_OPT(KUSB, Kern::Printf(" ep %d, buf %d, addr 0x%x", nextEp, k, pBuf )); - chunkInd++; - __ASSERT_DEBUG(chunkInd<=aHwChunks.Count(), - Kern::Printf(" Error: available chunks %d, run out at epInd%d, bufInd%d", - aHwChunks.Count(), i, k)); - __ASSERT_DEBUG(chunkInd<=aHwChunks.Count(), - Kern::Fault("usbc.ldd", __LINE__)); - } - } - } - - } - -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; - - for(TInt i=0;iiNext; - 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 - for(TInt i=0;iiChannelClosing) - 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)) != UsbShai::EUsbPeripheralNoState); - ++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 == UsbShai::EUsbPeripheralStateSuspended) - { - __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 == UsbShai::EUsbPeripheralStateConfigured); - TBool deconfigured = EFalse; - TInt cancellationCode = KErrNone; - if (aDeviceState == UsbShai::EUsbPeripheralStateSuspended) - { - __KTRACE_OPT(KUSB, Kern::Printf(" Suspending...")); - iOldDeviceState = iDeviceState; - // Put PSL into low power mode here - } - else - { - deconfigured = (iDeviceState == UsbShai::EUsbPeripheralStateConfigured && - aDeviceState != UsbShai::EUsbPeripheralStateConfigured); - if (iDeviceState == UsbShai::EUsbPeripheralStateConfigured) - { - if (aDeviceState == UsbShai::EUsbPeripheralStateUndefined) - cancellationCode = KErrUsbCableDetached; - else if (aDeviceState == UsbShai::EUsbPeripheralStateAddress) - cancellationCode = KErrUsbDeviceNotConfigured; - else if (aDeviceState == UsbShai::EUsbPeripheralStateDefault) - 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])); - - if (i == RDevUsbcClient::ERequestAlternateDeviceStatusNotify) - { - - iDeviceStatusNeeded = EFalse; - iStatusFifo->FlushQueue(); - - if (iStatusChangePtr) - { - iStatusChangeReq->Data() = iController->GetDeviceStatus(); - iStatusChangePtr = NULL; - - if (iStatusChangeReq->IsReady()) - { - iRequestStatus[i] = NULL; - Kern::QueueRequestComplete(iClient, iStatusChangeReq, - KErrDisconnected); - } - } - - } - else if (i == RDevUsbcClient::ERequestEndpointStatusNotify) - { - - 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; - } - - if (iEndpointStatusChangeReq->IsReady()) - { - iRequestStatus[i] = NULL; - Kern::QueueRequestComplete(iClient,iEndpointStatusChangeReq,KErrDisconnected); - } - - } - else if (i == RDevUsbcClient::ERequestOtgFeaturesNotify) - { - - if (iOtgFeatureChangePtr) - { - TUint8 features; - iController->GetCurrentOtgFeatures(features); - iOtgFeatureChangeReq->Data()=features; - iOtgFeatureChangePtr = NULL; - } - - if (iOtgFeatureChangeReq->IsReady()) - { - iRequestStatus[i] = NULL; - Kern::QueueRequestComplete(iClient, iOtgFeatureChangeReq, - KErrDisconnected); - } - - } - else - { - 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; - } - - UsbShai::TTransferDirection transferDir = iRequestCallbackInfo->iTransferDir; - TInt error = iRequestCallbackInfo->iError; - - switch (transferDir) - { - - case UsbShai::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 UsbShai::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 == UsbShai::KUsbEpTypeBulk) && (lastPacketSize & (maxPacketSize - 1))) - { - completeNow = ETrue; - } - else if ((type != UsbShai::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 != UsbShai::KUsbEpDirOut && - iEndpointInfo.iDir != UsbShai::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 != UsbShai::KUsbEpDirIn && - iEndpointInfo.iDir != UsbShai::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++) - { - iEpNumDeOrderedByBufSize[i] = -1; - 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; -} - -//---