sl@0: // Copyright (c) 2004-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: // f32test\testusbcldd\src\dlddtestusbcchannel.cpp sl@0: // sl@0: // sl@0: sl@0: #include "usbcdesc.h" sl@0: #include "dtestusblogdev.h" sl@0: #include "testusbc.h" sl@0: sl@0: extern TDynamicDfcQue* gDfcQ; sl@0: sl@0: const TUsbcEndpointData DLddTestUsbcChannel::iEndpointData[] = sl@0: { sl@0: {{KUsbEpSize64, (KUsbEpTypeControl | KUsbEpDirBidirect)}, EFalse}, sl@0: {{KUsbEpSize64, (KUsbEpTypeBulk | KUsbEpDirOut)}, EFalse}, sl@0: {{KUsbEpSize64, (KUsbEpTypeBulk | KUsbEpDirIn )}, EFalse}, sl@0: {{KUsbEpSize64, (KUsbEpTypeBulk | KUsbEpDirOut)}, EFalse}, sl@0: {{KUsbEpSize64, (KUsbEpTypeBulk | KUsbEpDirIn )}, EFalse}, sl@0: {{KUsbEpNotAvailable, KUsbEpNotAvailable}, EFalse} sl@0: }; sl@0: sl@0: // The EKA1 base class needs a DLogicalDevice* for its constructor sl@0: DLddTestUsbcChannel::DLddTestUsbcChannel(RPointerArray& aEndpoints) : sl@0: iDescriptors(NULL), sl@0: iIfcSet(this, 0), sl@0: iEndpoints(aEndpoints), sl@0: iDeviceState(EUsbcDeviceStateConfigured) sl@0: { sl@0: iClient = &Kern::CurrentThread(); sl@0: iClient->Open(); sl@0: } sl@0: sl@0: DLddTestUsbcChannel::~DLddTestUsbcChannel() sl@0: { sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/) sl@0: { sl@0: TInt err = KErrNone; sl@0: // Setup LDD for receiving client messages sl@0: SetDfcQ(gDfcQ); sl@0: iMsgQ.Receive(); sl@0: sl@0: _LIT(KEmptyString, ""); sl@0: err = iDescriptors.Init( sl@0: TUsbcDeviceDescriptor::New(0, 0, 0, 0, 0, 0, 0, 0), sl@0: TUsbcConfigDescriptor::New(0, ETrue, ETrue, 0), sl@0: TUsbcLangIdDescriptor::New(0), sl@0: TUsbcStringDescriptor::New(KEmptyString), sl@0: TUsbcStringDescriptor::New(KEmptyString), sl@0: TUsbcStringDescriptor::New(KEmptyString), sl@0: TUsbcStringDescriptor::New(KEmptyString) sl@0: ); sl@0: sl@0: return err; sl@0: } sl@0: sl@0: void DLddTestUsbcChannel::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: 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: DTestUsbcEndpoint* pEndpoint = NULL; sl@0: switch (mask) sl@0: { sl@0: case RDevUsbcClient::ERequestEp0Cancel: sl@0: pEndpoint = iEndpoints[0]; sl@0: pEndpoint->DoCancel(); sl@0: break; sl@0: case RDevUsbcClient::ERequestEp1Cancel: sl@0: pEndpoint = iEndpoints[FindRealEndpoint(1)]; sl@0: pEndpoint->DoCancel(); sl@0: break; sl@0: case RDevUsbcClient::ERequestEp2Cancel: sl@0: pEndpoint = iEndpoints[FindRealEndpoint(2)]; sl@0: pEndpoint->DoCancel(); sl@0: break; sl@0: case RDevUsbcClient::ERequestEp3Cancel: sl@0: pEndpoint = iEndpoints[FindRealEndpoint(3)]; sl@0: pEndpoint->DoCancel(); sl@0: break; sl@0: case RDevUsbcClient::ERequestEp4Cancel: sl@0: pEndpoint = iEndpoints[FindRealEndpoint(4)]; sl@0: pEndpoint->DoCancel(); sl@0: break; sl@0: case RDevUsbcClient::ERequestEp5Cancel: sl@0: pEndpoint = iEndpoints[FindRealEndpoint(5)]; sl@0: pEndpoint->DoCancel(); sl@0: break; sl@0: case RDevUsbcClient::ERequestAlternateDeviceStatusNotifyCancel: sl@0: CancelAlternateDeviceStatusNotify(); sl@0: break; sl@0: default: sl@0: m.Complete(KErrNotSupported, ETrue); sl@0: return; 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: TInt DLddTestUsbcChannel::DoCancel(TInt /*aReqNo*/) sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DLddTestUsbcChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DoRequest 0x%08x"),aReqNo)); sl@0: TInt r = KErrNone; sl@0: //If request is ep number then do a transfer request. sl@0: if(aReqNo > KUsbcMaxEpNumber) sl@0: { sl@0: if (aReqNo == RDevTestUsbcClient::ETestRequestNotifyEndpointStatus) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("ETestRequestNotifyEndpointStatus"))); sl@0: r = HostEndpointStatusNotify((TInt)a1, aStatus); sl@0: } sl@0: else if (aReqNo == RDevUsbcClient::ERequestAlternateDeviceStatusNotify) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("ERequestAlternateDeviceStatusNotify"))); sl@0: r = SetAlternateDeviceStatusNotify(aStatus, (TUint*)a1); sl@0: } sl@0: else if (aReqNo == RDevUsbcClient::ERequestReEnumerate) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("ERequestReEnumerate"))); sl@0: r = ReEnumerate((TRequestStatus*)a1); sl@0: } sl@0: else sl@0: { sl@0: Kern::RequestComplete(iClient, aStatus, KErrNotSupported); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: r = DoTransferAsyncReq(aReqNo, a1, a2, *aStatus); sl@0: } sl@0: sl@0: if (r != KErrNone) sl@0: { sl@0: Kern::RequestComplete(iClient, aStatus, r); sl@0: } sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2) sl@0: { sl@0: TInt r=KErrNone; sl@0: TDes8& a1Buf = *((TDes8*)a1); sl@0: TDes8& a2Buf = *((TDes8*)a2); sl@0: TPtrC8 pZeroDesc(NULL,0); sl@0: sl@0: sl@0: switch (aFunction) sl@0: { sl@0: case RDevUsbcClient::EControlEndpointZeroRequestError: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlEndpointZeroRequestError"))); sl@0: r = KErrNone; sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlEndpointCaps: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlEndpointCaps"))); sl@0: r = __THREADWRITE(iClient, a1, pZeroDesc); sl@0: if(r == KErrNone) sl@0: { sl@0: TBuf8 aBuf; sl@0: memclr(&aBuf, sizeof(aBuf)); sl@0: TPtr8 endpointCfg((TUint8*)&aBuf,0,sizeof(aBuf)); sl@0: sl@0: r = Kern::ThreadDesRead(iClient,a1,endpointCfg,0,0); sl@0: if(r == KErrNone) sl@0: { sl@0: endpointCfg.Copy(reinterpret_cast(iEndpointData), sl@0: Min(endpointCfg.MaxLength(), sl@0: sizeof(TUsbcEndpointData[5]))); sl@0: r = Kern::ThreadDesWrite(iClient,a1,endpointCfg,0,KTruncateToMaxLength,iClient); sl@0: } sl@0: } sl@0: sl@0: if(r != KErrNone) sl@0: { sl@0: __THREADPANIC(iClient, r); sl@0: } sl@0: sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlDeviceCaps: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlDeviceCaps"))); sl@0: r = __THREADWRITE(iClient, a1, pZeroDesc); sl@0: if(r!=KErrNone) sl@0: { sl@0: __THREADPANIC(iClient, r); sl@0: } sl@0: TUsbDeviceCaps caps; sl@0: caps().iTotalEndpoints = KMaxEndpointsPerClient; sl@0: caps().iConnect = ETrue; sl@0: caps().iSelfPowered = ETrue; sl@0: caps().iRemoteWakeup = ETrue; sl@0: TBuf8 aBuf; sl@0: memclr(&aBuf, sizeof(aBuf)); sl@0: TPtr8 cfg((TUint8*)&aBuf,0,sizeof(aBuf)); sl@0: r=Kern::ThreadDesRead(iClient,a1,cfg,0,0); sl@0: cfg = caps.Left(Min(caps.Length(), cfg.MaxLength())); sl@0: r=Kern::ThreadDesWrite(iClient,a1,cfg,0,KTruncateToMaxLength,iClient); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlDeviceStatus: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlDeviceStatus"))); sl@0: r = __THREADRAWWRITE(iClient, a1, (TUint8*)&iDeviceState, (TInt)sizeof(iDeviceState)); sl@0: if(r != KErrNone) sl@0: { sl@0: __THREADPANIC(iClient, r); sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlHaltEndpoint: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlHaltEndpoint"))); sl@0: r = HaltClearEndpoint(ETrue, (TInt)a1); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetDeviceDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetDeviceDescriptor"))); sl@0: r = __THREADWRITE(iClient, a1, pZeroDesc); sl@0: if(r != KErrNone) sl@0: { sl@0: __THREADPANIC(iClient, r); sl@0: } sl@0: r = iDescriptors.GetDeviceDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlSetDeviceDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlSetDeviceDescriptor"))); sl@0: r = iDescriptors.SetDeviceDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetDeviceDescriptorSize: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetDeviceDescriptorSize"))); sl@0: if(a1 != NULL) sl@0: { sl@0: const TPtrC8 size(reinterpret_cast(&KUsbDescSize_Device), sizeof(KUsbDescSize_Device)); sl@0: r = __THREADWRITE(iClient, a1, size); sl@0: } sl@0: else sl@0: { sl@0: r = KErrArgument; sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetConfigurationDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetConfigurationDescriptor"))); sl@0: r = __THREADWRITE(iClient, a1, pZeroDesc); // set client descriptor length to zero sl@0: if(r != KErrNone) sl@0: { sl@0: __THREADPANIC(iClient, r); sl@0: } sl@0: r = iDescriptors.GetConfigurationDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlSetConfigurationDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlSetConfigurationDescriptor"))); sl@0: r = iDescriptors.SetConfigurationDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetConfigurationDescriptorSize: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetConfigurationDescriptorSize"))); sl@0: if(a1 != NULL) sl@0: { sl@0: const TPtrC8 size(reinterpret_cast(&KUsbDescSize_Config), sizeof(KUsbDescSize_Config)); sl@0: r = __THREADWRITE(iClient, a1, size); sl@0: } sl@0: else sl@0: { sl@0: r=KErrArgument; sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetInterfaceDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetInterfaceDescriptor"))); sl@0: r = iDescriptors.GetInterfaceDescriptorTC(iClient, a2Buf, 0, (TInt)a1); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlSetInterfaceDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlSetInterfaceDescriptor"))); sl@0: TBuf8 new_ifc; sl@0: r = __THREADWRITE(iClient, a2, new_ifc); sl@0: if (r != KErrNone) sl@0: { sl@0: break; sl@0: } sl@0: r = iDescriptors.SetInterfaceDescriptor(new_ifc, 0, (TInt)a1); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetInterfaceDescriptorSize: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetInterfaceDescriptorSize"))); sl@0: if (a2 != NULL) sl@0: { sl@0: const TPtrC8 size(reinterpret_cast(&KUsbDescSize_Interface), sizeof(KUsbDescSize_Interface)); sl@0: r = __THREADWRITE(iClient, a2, size); sl@0: } sl@0: else sl@0: { sl@0: r = KErrArgument; sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetEndpointDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetEndpointDescriptor"))); sl@0: TEndpointDescriptorInfo info; sl@0: r = __THREADRAWREAD(iClient, a1,(TUint8*)&info, (TInt)sizeof(info)); sl@0: if(r != KErrNone) sl@0: { sl@0: __THREADPANIC(iClient, r); sl@0: } sl@0: r = iDescriptors.GetEndpointDescriptorTC(iClient, *((TDes8*)info.iArg), 0, info.iSetting, (TUint8)info.iEndpoint); sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlSetEndpointDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlSetEndpointDescriptor"))); sl@0: TEndpointDescriptorInfo info; sl@0: r = __THREADRAWREAD(iClient, a1, (TUint8*)&info, (TInt)sizeof(TEndpointDescriptorInfo)); sl@0: if(r != KErrNone) sl@0: __THREADPANIC(iClient, r); sl@0: r = iDescriptors.SetEndpointDescriptorTC(iClient, *((TDes8*)info.iArg), 0, info.iSetting, (TUint8)info.iEndpoint); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetEndpointDescriptorSize: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetEndpointDescriptorSize"))); sl@0: TEndpointDescriptorInfo info; sl@0: r = __THREADRAWREAD(iClient, a1, (TUint8*)&info, (TInt)sizeof(TEndpointDescriptorInfo)); sl@0: if(r != KErrNone) sl@0: __THREADPANIC(iClient, r); sl@0: TInt s; sl@0: TInt r = iDescriptors.GetEndpointDescriptorSize(0, info.iSetting, (TUint8)info.iEndpoint, s); sl@0: if (r == KErrNone) sl@0: { sl@0: TPtrC8 size(reinterpret_cast(&s), sizeof(s)); sl@0: r = __THREADWRITE(iClient, &(info.iArg), size); sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlSetCSInterfaceDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlSetCSInterfaceDescriptor"))); sl@0: TCSDescriptorInfo info; sl@0: r = __THREADRAWREAD(iClient, a1, (TUint8*)&info, (TInt)sizeof(TCSDescriptorInfo)); sl@0: if(r != KErrNone) sl@0: __THREADPANIC(iClient, r); sl@0: r = iDescriptors.SetCSInterfaceDescriptorTC(iClient, *((TDes8*)info.iArg), 0, info.iSetting, info.iSize); sl@0: } sl@0: break; sl@0: sl@0: case RDevUsbcClient::EControlDeviceDisconnectFromHost: sl@0: { sl@0: r = KErrNone; sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlDeviceConnectToHost: sl@0: { sl@0: r = KErrNone; sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlDevicePowerUpUdc: sl@0: { sl@0: r = KErrNone; sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlSetInterface: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlSetInterface"))); sl@0: TUsbcIfcInfo info; sl@0: r = __THREADRAWREAD(iClient, a2, (TUint8*)&info, (TInt)sizeof(TUsbcIfcInfo)); sl@0: if(r != KErrNone) sl@0: __THREADPANIC(iClient, r); sl@0: sl@0: TUsbcInterfaceInfoBuf* interfaceData = info.iInterfaceData; sl@0: TPtr8* ifcString = info.iString; sl@0: r = SetInterface((TInt)a1, interfaceData, ifcString); sl@0: } sl@0: break; sl@0: sl@0: case RDevUsbcClient::EControlReleaseInterface: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlReleaseInterface"))); sl@0: r = ReleaseInterface((TInt)a1); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetManufacturerStringDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetManufacturerStringDescriptor"))); sl@0: r = iDescriptors.GetManufacturerStringDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlSetManufacturerStringDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlSetManufacturerStringDescriptor"))); sl@0: r = iDescriptors.SetManufacturerStringDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetProductStringDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetManufacturerStringDescriptor"))); sl@0: r = iDescriptors.GetProductStringDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlSetProductStringDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlSetProductStringDescriptor"))); sl@0: r = iDescriptors.SetProductStringDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetSerialNumberStringDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetManufacturerStringDescriptor"))); sl@0: r = iDescriptors.GetSerialNumberStringDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlSetSerialNumberStringDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlSetSerialNumberStringDescriptor"))); sl@0: r = iDescriptors.SetSerialNumberStringDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlGetConfigurationStringDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlGetManufacturerStringDescriptor"))); sl@0: r = iDescriptors.GetConfigurationStringDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: sl@0: case RDevUsbcClient::EControlSetConfigurationStringDescriptor: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("EControlSetConfigurationStringDescriptor"))); sl@0: r = iDescriptors.SetConfigurationStringDescriptorTC(iClient, a1Buf); sl@0: break; sl@0: } sl@0: case RDevUsbcClient::EControlEndpointStatus: sl@0: { sl@0: TInt ep = (TInt)a1; sl@0: DTestUsbcEndpoint* pEndpoint = iEndpoints[FindRealEndpoint(ep)]; sl@0: TEndpointState state = EEndpointStateUnknown; sl@0: if (pEndpoint->IsHalted()) sl@0: { sl@0: state = EEndpointStateStalled; sl@0: } sl@0: else sl@0: { sl@0: state = EEndpointStateNotStalled; sl@0: } sl@0: __THREADRAWWRITE(iClient, a2, (TUint8*)&state, (TInt)sizeof(state)); sl@0: break; sl@0: } sl@0: sl@0: case RDevTestUsbcClient::ETestControlReqEndpointStatusNotify: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("ETestControlReqEndpointStatusNotify"))); sl@0: r = HostEndpointStatusNotify((TInt)a2, (TRequestStatus*)a1); sl@0: break; sl@0: } sl@0: sl@0: case RDevTestUsbcClient::ETestControlClearEndpoint: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("ETestControlClearEndpoint"))); sl@0: r = ClearEndpoint((TInt)a1); sl@0: break; sl@0: } sl@0: sl@0: default: sl@0: r = KErrNotSupported; sl@0: } sl@0: sl@0: return r; sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::SetInterface(TInt aInterfaceNumber, sl@0: TUsbcInterfaceInfoBuf *aUserInterfaceInfoBuf, sl@0: TPtr8* aInterfaceString) sl@0: { sl@0: // The Interface Descriptor string is no interest to us sl@0: // so leave that as is, the controller will have to take a local copy sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("SetInterface Entry Interface#=%d Endpoints =%d"),aInterfaceNumber,(*aUserInterfaceInfoBuf)().iTotalEndpointsUsed)); sl@0: TInt r = KErrNone; sl@0: TUsbcEndpointInfo* pEndpointData=NULL; sl@0: TInt numberOfEndpoints=0; sl@0: TUsbcInterfaceInfoBuf interfaceBuff; sl@0: TInt bufLen=interfaceBuff.Length(); sl@0: TInt srcLen=__THREADDESLEN(iClient,aUserInterfaceInfoBuf); sl@0: if(srcLen Warning: deleting current interface setting"))); sl@0: iIfcSet.iCurrentInterface = 0; sl@0: } sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::CreateEndpoints(TUsbcInterface* aIfc, TInt aEndpointsUsed, sl@0: const TUsbcEndpointInfo aEndpointData[]) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DLddTestUsbcChannel::CreateEndpoints()"))); sl@0: sl@0: for (TInt i = 0; i < aEndpointsUsed; ++i) sl@0: { sl@0: for (TInt j = 1; j <= KMaxEndpointsPerClient; ++j) sl@0: { sl@0: if (iEndpoints[j]->EndpointSuitable(aEndpointData[i])) sl@0: { sl@0: TUsbcLogicalEndpoint* const ep = new TUsbcLogicalEndpoint(j, aEndpointData[i], aIfc); sl@0: if (!ep) sl@0: { sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: new TUsbcLogicalEndpoint() failed"))); sl@0: aIfc->iEndpoints.ResetAndDestroy(); sl@0: for (TInt k = 1; k <= KMaxEndpointsPerClient; ++k) sl@0: { sl@0: iEndpoints[k]->iReserve = EFalse; sl@0: } sl@0: return KErrNoMemory; sl@0: } sl@0: iEndpoints[j]->iReserve = ETrue; sl@0: iEndpoints[j]->SetClearCallback(this); sl@0: aIfc->iEndpoints.Append(ep); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TBool DLddTestUsbcChannel::ValidateEndpoint(TUsbcEndpointInfo* aEndpointInfo) sl@0: { // Quick sanity check on endpoint properties sl@0: TUint dir=aEndpointInfo->iDir; sl@0: TInt size=aEndpointInfo->iSize; sl@0: if(size <=0) sl@0: return EFalse; 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 > 1023) sl@0: return EFalse; sl@0: break; sl@0: case KUsbEpTypeBulk: sl@0: if((dir != KUsbEpDirIn && dir != KUsbEpDirOut) || size > 64) sl@0: return EFalse; sl@0: break; sl@0: case KUsbEpTypeInterrupt: sl@0: if((dir != KUsbEpDirIn && dir != KUsbEpDirOut) || size > 64) 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: TInt DLddTestUsbcChannel::SetupIfcDescriptor(TUsbcInterface* aIfc, TUsbcClassInfo& aClass, sl@0: TDesC8* aString, const TUsbcEndpointInfo aEndpointData[]) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DLddTestUsbcChannel::SetupIfcDescriptor()"))); sl@0: sl@0: // interface descriptor sl@0: TUsbcDescriptorBase* d = TUsbcInterfaceDescriptor::New(aIfc->iInterfaceSet->iInterfaceNumber, sl@0: aIfc->iSettingCode, sl@0: aIfc->iEndpoints.Count(), sl@0: aClass); sl@0: if (!d) sl@0: { sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" > Error: Memory allocation for ifc desc failed."))); sl@0: return KErrNoMemory; sl@0: } sl@0: iDescriptors.InsertDescriptor(d); sl@0: sl@0: // interface string descriptor sl@0: if (aString) sl@0: { sl@0: // we don't know the length of the string, so we have to allocate memory dynamically sl@0: TUint strlen = __THREADDESLEN(iClient, aString); sl@0: if (strlen > KUsbStringDescStringMaxSize) sl@0: { sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Warning: $ descriptor too long - string will be truncated"))); sl@0: strlen = KUsbStringDescStringMaxSize; sl@0: } sl@0: sl@0: HBuf8Plat* stringbuf = NULL; sl@0: __NEWPLATBUF(stringbuf, strlen); sl@0: if (!stringbuf) sl@0: { sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" > Error: Memory allocation for ifc $ desc string failed."))); sl@0: iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber, aIfc->iSettingCode); sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: TInt r; sl@0: __THREADREADPLATBUF(iClient, aString, stringbuf, r); sl@0: if (r != KErrNone) sl@0: { sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" > Error: Thread read error!"))); sl@0: iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber, sl@0: aIfc->iSettingCode); sl@0: delete stringbuf; sl@0: return r; sl@0: } sl@0: TUsbcStringDescriptor* const sd = TUsbcStringDescriptor::New(*stringbuf); sl@0: if (!sd) sl@0: { sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" > Error: Memory allocation for ifc $ desc failed."))); sl@0: iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber, aIfc->iSettingCode); sl@0: delete stringbuf; sl@0: return KErrNoMemory; sl@0: } sl@0: iDescriptors.SetIfcStringDescriptor(sd, aIfc->iInterfaceSet->iInterfaceNumber, aIfc->iSettingCode); sl@0: delete stringbuf; // the (EPOC) descriptor was copied by New() sl@0: } sl@0: sl@0: // endpoint descriptors sl@0: for (TInt i = 0; i < aIfc->iEndpoints.Count(); ++i) sl@0: { sl@0: // The reason for using another function argument for Endpoint Info - and not possibly (similar to the sl@0: // Endpoint Address) "aIfc->iEndpoints[i]->iPEndpoint->iLEndpoint->iInfo" - is that at this time sl@0: // there are no logical endpoints associated with our real endpoints, i.e. iLEndpoint is NULL! sl@0: if (aEndpointData[i].iExtra) sl@0: { sl@0: // if non-standard endpoint descriptor requested... sl@0: if (aEndpointData[i].iExtra != 2) sl@0: { sl@0: // ...then it must be a Audio Class endpoint descriptor. Else... sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" > We only support EP desc extension of 2 bytes (not %d)"), aEndpointData[i].iExtra)); sl@0: iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber, sl@0: aIfc->iSettingCode); sl@0: return KErrArgument; sl@0: } sl@0: d = TUsbcAudioEndpointDescriptor::New((TUint8)i, aEndpointData[i]); sl@0: } sl@0: else sl@0: { sl@0: d = TUsbcEndpointDescriptor::New((TUint8)i, aEndpointData[i]); sl@0: } sl@0: if (!d) sl@0: { sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" > Memory allocation for ep desc #%d failed."), i)); sl@0: iDescriptors.DeleteIfcDescriptor(aIfc->iInterfaceSet->iInterfaceNumber, sl@0: aIfc->iSettingCode); sl@0: return KErrNoMemory; sl@0: } sl@0: iDescriptors.InsertDescriptor(d); sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** sl@0: @internalTechnology sl@0: sl@0: Releases an existing USB interface (one setting), complete with endpoints, descriptors, etc., sl@0: and removes it from the internal device configuration tree. sl@0: sl@0: @param aClientId A pointer to the LDD owning the interface. sl@0: @param aInterfaceNumber The setting number of the interface setting to be deleted. This must be sl@0: the highest numbered (or 'last') setting for this interface. sl@0: sl@0: @return KErrNotFound if interface (not setting) for some reason cannot be found, KErrArgument if an sl@0: invalid interface setting number is specified (not existing or existing but too small), KErrNone if sl@0: interface successfully released or if this client doesn't own any interface. sl@0: */ sl@0: TInt DLddTestUsbcChannel::ReleaseInterface(TInt aInterfaceNumber) sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DLddTestUsbcChannel::ReleaseInterface(..., %d)"), aInterfaceNumber)); sl@0: const TInt setting_count = iIfcSet.iInterfaces.Count(); sl@0: if ((aInterfaceNumber != 0) && ((setting_count - 1) != aInterfaceNumber)) sl@0: { sl@0: __KTRACE_OPT(KUSB, sl@0: Kern::Printf(__KSTRING(" > Error: interface settings must be released in descending order:\n\r%d settings exist, #%d was requested to be released: release %d first)"), sl@0: setting_count, aInterfaceNumber, setting_count - 1)); sl@0: return KErrArgument; sl@0: } sl@0: // Reset reserved status of the endpoints sl@0: for (TInt i = 0; i < KMaxEndpointsPerClient+1; i++) sl@0: { sl@0: iEndpoints[i]->iReserve = EFalse; sl@0: } sl@0: if (aInterfaceNumber == 0) sl@0: { sl@0: TInt m = iIfcSet.iInterfaces.Count(); sl@0: while (m > 0) sl@0: { sl@0: m--; sl@0: // Delete the setting itself + its ifc & ep descriptors sl@0: DeleteInterface(m); sl@0: iDescriptors.DeleteIfcDescriptor(0, m); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // Delete the setting itself + its ifc & ep descriptors sl@0: DeleteInterface(aInterfaceNumber); sl@0: iDescriptors.DeleteIfcDescriptor(0, aInterfaceNumber); sl@0: } sl@0: // Delete the whole interface if all settings are gone sl@0: if (iIfcSet.iInterfaces.Count() == 0) sl@0: { sl@0: DeleteInterfaceSet(); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DLddTestUsbcChannel::DeleteInterfaceSet() sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DLddTestUsbcChannel::DeleteInterfaceSet"))); sl@0: iIfcSet.iInterfaceNumber = 0; sl@0: iIfcSet.iCurrentInterface = 0; sl@0: iIfcSet.iInterfaces.ResetAndDestroy(); sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::DoTransferAsyncReq(TInt aEndpointNumber, TAny* a1, TAny* a2, TRequestStatus& aStatus) sl@0: { sl@0: TInt r = KErrNone; sl@0: DTestUsbcEndpoint* pEndpoint = NULL; sl@0: TEndpointTransferInfo *pTfr = NULL; sl@0: sl@0: sl@0: if(!ValidEndpoint(aEndpointNumber)) sl@0: { sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING("DoRequest Read: in error complete"))); sl@0: return KErrUsbEpNotInInterface; sl@0: } sl@0: sl@0: if(a1 == NULL) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: sl@0: TBool hostTransfer = EFalse; sl@0: if(a2 != NULL) sl@0: { sl@0: hostTransfer = ETrue; sl@0: } sl@0: sl@0: TEndpointTransferInfo transferInfo; sl@0: pTfr = (TEndpointTransferInfo*)&transferInfo; sl@0: r = __THREADRAWREAD(iClient, a1, (TUint8*)&transferInfo, sizeof(TEndpointTransferInfo)); sl@0: if(r != KErrNone) sl@0: { sl@0: __THREADPANIC(iClient, r); sl@0: } sl@0: if (aEndpointNumber != 0) sl@0: { sl@0: if (hostTransfer) sl@0: { sl@0: pEndpoint = iEndpoints[aEndpointNumber]; sl@0: } sl@0: else sl@0: { sl@0: pEndpoint = iEndpoints[FindRealEndpoint(aEndpointNumber)]; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: pEndpoint = iEndpoints[0]; sl@0: } sl@0: if(!pEndpoint) sl@0: { sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING("DoRequest Read: in error complete"))); sl@0: return KErrUsbEpNotInInterface; sl@0: } sl@0: sl@0: switch(pTfr->iTransferType) sl@0: { sl@0: case ETransferTypeReadUntilShort: sl@0: case ETransferTypeReadData: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DoRequest Read"))); sl@0: sl@0: if(!hostTransfer && !pEndpoint->SupportsDir(KUsbEpDirOut) && !pEndpoint->SupportsDir(KUsbEpDirBidirect)) sl@0: { // Trying to make the wrong thing sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING("DoRequest Read: in error complete"))); sl@0: r = KErrUsbEpBadDirection; sl@0: break; sl@0: } 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 = __THREADWRITE(iClient, pTfr->iDes, pZeroDesc); // set client descriptor length to zero sl@0: if(r != KErrNone) sl@0: __THREADPANIC(iClient, r); sl@0: if (hostTransfer) sl@0: r = pEndpoint->NewHostRequest(iClient, &aStatus, *pTfr, pTfr->iTransferType); sl@0: else sl@0: r = pEndpoint->NewRequest(iClient, &aStatus, *pTfr, pTfr->iTransferType); sl@0: break; sl@0: } sl@0: sl@0: case ETransferTypeWrite: sl@0: { sl@0: __KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("DoRequest Write 1"))); sl@0: if(!hostTransfer && !pEndpoint->SupportsDir(KUsbEpDirIn) && !pEndpoint->SupportsDir(KUsbEpDirBidirect)) sl@0: { sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING("DoRequest Write: wrong direction complete"))); sl@0: r = KErrUsbEpBadDirection; sl@0: break; sl@0: } sl@0: if (hostTransfer) sl@0: r = pEndpoint->NewHostRequest(iClient, &aStatus, *pTfr, ETransferTypeWrite); sl@0: else sl@0: r = pEndpoint->NewRequest(iClient, &aStatus, *pTfr, ETransferTypeWrite); sl@0: break; sl@0: } sl@0: default: sl@0: __KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING("DoRequest Not supported complete"))); sl@0: r = KErrNotSupported; sl@0: break; sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::HaltClearEndpoint(TBool aHalt, TInt aEndpointNumber) sl@0: { sl@0: DTestUsbcEndpoint* pEndpoint = NULL; sl@0: if (aEndpointNumber != 0) sl@0: { sl@0: pEndpoint = iEndpoints[FindRealEndpoint(aEndpointNumber)]; sl@0: } sl@0: else sl@0: { sl@0: pEndpoint = iEndpoints[0]; sl@0: } sl@0: TInt err; sl@0: if (aHalt) sl@0: { sl@0: err = pEndpoint->Halt(); sl@0: } sl@0: else sl@0: { sl@0: err = pEndpoint->Clear(); sl@0: } sl@0: return err; sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::HostEndpointStatusNotify(TInt aEndpointNumber, TRequestStatus* aStatus) sl@0: { sl@0: DTestUsbcEndpoint* pEndpoint = iEndpoints[aEndpointNumber]; sl@0: return pEndpoint->HostStatusNotify(iClient, aStatus); sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::ClearEndpoint(TInt aEndpointNumber) sl@0: { sl@0: DTestUsbcEndpoint* pEndpoint = iEndpoints[aEndpointNumber]; sl@0: return pEndpoint->Clear(); sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::EndpointStatusNotify(TUint* aEndpointMask, TRequestStatus* aStatus) sl@0: { sl@0: iEndpointStatusMask = aEndpointMask; sl@0: iEndpointStatusNotifyRequest = aStatus; sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DLddTestUsbcChannel::EndpointStatusNotifyCallback() sl@0: { sl@0: if (iEndpointStatusNotifyRequest == NULL || iEndpointStatusMask == NULL) sl@0: { sl@0: return; sl@0: } sl@0: sl@0: //Get status for interface's endpoints. sl@0: //NOTE: currently we only support one interface. sl@0: TUsbcInterface* interface = iIfcSet.iInterfaces[0]; sl@0: TUint bitmask = 0; sl@0: for (TInt i = interface->iEndpoints.Count() - 1; i >= 0; i--) sl@0: { sl@0: TUsbcLogicalEndpoint* logep = interface->iEndpoints[i]; sl@0: DTestUsbcEndpoint* pEndpoint = iEndpoints[FindRealEndpoint(logep->iLEndpointNum)]; sl@0: if (pEndpoint->IsHalted()) sl@0: { sl@0: bitmask |= 1; sl@0: bitmask = bitmask << 1; sl@0: } sl@0: } sl@0: sl@0: //Write bitmask back to client space. sl@0: TInt r = __THREADRAWWRITE(iClient, (void*)iEndpointStatusMask, (TUint8*)&bitmask, (TInt)sizeof(bitmask)); sl@0: sl@0: //Complete client request. sl@0: Kern::RequestComplete(iClient, iEndpointStatusNotifyRequest, r); sl@0: sl@0: iEndpointStatusMask = NULL; sl@0: iEndpointStatusNotifyRequest = NULL; sl@0: } sl@0: sl@0: TBool DLddTestUsbcChannel::ValidEndpoint(TInt aEndpointNumber) sl@0: { sl@0: return (aEndpointNumber <= 5 && aEndpointNumber >= 0); sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::FindRealEndpoint(TInt aEndpointNumber) sl@0: { sl@0: TUsbcInterface* pIfc = iIfcSet.CurrentInterface(); sl@0: return pIfc->iEndpoints[aEndpointNumber - 1]->iLEndpointNum; sl@0: } sl@0: sl@0: void DLddTestUsbcChannel::AlternateDeviceStatusNotify() sl@0: { sl@0: if (iAlternateDeviceStatusNotifyRequest != NULL) sl@0: { sl@0: TInt r = __THREADRAWWRITE(iClient, (void*)iAlternateDeviceStatusNotifyValue, (TUint8*)&iDeviceState, (TInt)sizeof(iDeviceState)); sl@0: Kern::RequestComplete(iClient, iAlternateDeviceStatusNotifyRequest, r); sl@0: iAlternateDeviceStatusNotifyRequest = NULL; sl@0: } sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::SetAlternateDeviceStatusNotify(TRequestStatus* aStatus, TUint* aValue) sl@0: { sl@0: if (iAlternateDeviceStatusNotifyRequest != NULL) sl@0: { sl@0: return KErrInUse; sl@0: } sl@0: sl@0: TRequestStatus s; sl@0: s = KRequestPending; sl@0: sl@0: __THREADRAWWRITE(iClient, (void*)aStatus, (TUint8*)&s, (TInt)sizeof(s)); sl@0: iAlternateDeviceStatusNotifyRequest = aStatus; sl@0: iAlternateDeviceStatusNotifyValue = aValue; sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DLddTestUsbcChannel::CancelAlternateDeviceStatusNotify() sl@0: { sl@0: if (iAlternateDeviceStatusNotifyRequest != NULL) sl@0: { sl@0: __THREADRAWWRITE(iClient, (void*)iAlternateDeviceStatusNotifyValue, (TUint8*)&iDeviceState, (TInt)sizeof(iDeviceState)); sl@0: Kern::RequestComplete(iClient, iAlternateDeviceStatusNotifyRequest, KErrCancel); sl@0: iAlternateDeviceStatusNotifyRequest = NULL; sl@0: } sl@0: } sl@0: sl@0: TInt DLddTestUsbcChannel::ReEnumerate(TRequestStatus* aStatus) sl@0: { sl@0: SetDeviceState(EUsbcDeviceStateConfigured); sl@0: Kern::RequestComplete(iClient, aStatus, KErrNone); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DLddTestUsbcChannel::SetDeviceState(TUsbcDeviceState aState) sl@0: { sl@0: iDeviceState = aState; sl@0: AlternateDeviceStatusNotify(); sl@0: } sl@0: