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