diff -r 000000000000 -r a41df078684a kerneltest/e32test/usbho/t_otgdi/src/otgroot.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/usbho/t_otgdi/src/otgroot.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,1062 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// @internalComponent +// +// + +#include +#include +#include // unicode builds +#include +#include +#include +#include // RTest header +#include +#include +#include // OTGDI header +#include // USBCC header +#include "otgroot.h" +#include "testcaseroot.h" + +RUsbOtgDriver oUsbOtgDriver; +RDevUsbcClient oUsbcClient; + + +//===================================================================================== + +/* this class wraps all OTGDI calls as well to simplify + calling and normalising object access. - it has no base-class hence we can use multiple-inheritance + */ + COtgRoot::COtgRoot() + { + iOptActive = EFalse; + SetLoaded(EFalse); + } + + +/** otgLoadLdd +*/ +TInt COtgRoot::otgLoadLdd() + { + + LOG_FUNC + LOG_VERBOSE2(_L("Load driver: %S\n"), &KOTGDeviceInterfaceDriverName); + + if (!LddLoaded()) + { + + // load ldd device drivers (load otg only, it will load the needed stuff for us) + TInt err(User::LoadLogicalDevice(KOTGDeviceInterfaceDriverName)); + if ( (err != KErrNone) && (err != KErrAlreadyExists) ) + { + test.Printf(_L(" Unable to load driver: %S\n"), err, &KOTGDeviceInterfaceDriverName); + SetLoaded(EFalse); + return(err); + } + else + { + LOG_VERBOSE2(_L("Loaded driver: '%S' OK\n"), &KOTGDeviceInterfaceDriverName); + SetLoaded(ETrue); + } + + } + return(KErrNone); + } + + +/** otgOpen +*/ +TInt COtgRoot::otgOpen() + { + LOG_FUNC + + LOG_VERBOSE2(_L("Opening session... loaded = %d\n"), LddLoaded()); + + TInt err(oUsbOtgDriver.Open()); + if (err != KErrNone) + { + test.Printf(_L(" Unable to open a channel to USB OTG driver\n"),err); + return(err); + } + else + { + LOG_VERBOSE1(_L("Open channel OK\n")); + } + + return(KErrNone); + } + + +/** otgClose +*/ +void COtgRoot::otgClose() + { + LOG_FUNC + + test.Printf(_L("Closing session... loaded = %d\n"), LddLoaded()); + oUsbOtgDriver.Close(); + } + + +/* otgActivateOptTestMode + */ +TInt COtgRoot::otgActivateOptTestMode() + { + LOG_FUNC + + TInt err = oUsbOtgDriver.ActivateOptTestMode(); + + return(err); + } + + +/** otgStartStacks +*/ +TInt COtgRoot::otgStartStacks() + { + LOG_FUNC + + TInt err(oUsbOtgDriver.StartStacks()); + if (err != KErrNone) + { + + LOG_FUNCERROR(err) + + } + return(err); + + } + + +/** otgStopStacks +*/ +void COtgRoot::otgStopStacks() + { + LOG_FUNC + + oUsbOtgDriver.StopStacks(); + } + + +/** otgUnloadLdd +*/ +void COtgRoot::otgUnloadLdd() + { + + // code to unload the OTG ldd driver + TInt err (User::FreeLogicalDevice(KOTGDeviceInterfaceDriverName)); + if (err != KErrNone) + { + LOG_FUNCERROR(err) + } + + SetLoaded(EFalse); + } + + +/** otgQueueOtgEventRequest +*/ +void COtgRoot::otgQueueOtgEventRequest(RUsbOtgDriver::TOtgEvent& aEvent, TRequestStatus &aStatus) + { + //LOG_FUNC + LOG_VERBOSE2(_L("Queue an Event Request %08X.\n"), (TInt)(&aStatus)); + + oUsbOtgDriver.QueueOtgEventRequest(aEvent, aStatus); + + } + + +/** otgCancelOtgEventRequest +*/ +void COtgRoot::otgCancelOtgEventRequest() + { + LOG_VERBOSE1(_L("Cancel Event Request.\n")); + oUsbOtgDriver.CancelOtgEventRequest(); + } + + +/** otgQueueOtgMessageRequest +*/ +void COtgRoot::otgQueueOtgMessageRequest(RUsbOtgDriver::TOtgMessage& aMessage, TRequestStatus &aStatus) + { + //LOG_FUNC + LOG_VERBOSE2(_L("Queue a Message Request %08X.\n"), (TInt)(&aStatus)); + + //LOG_VERBOSE1(_L("Queue a Message Request.\n")); + oUsbOtgDriver.QueueOtgMessageRequest(aMessage, aStatus); + + } + + +/** otgCancelOtgMessageRequest +*/ +void COtgRoot::otgCancelOtgMessageRequest() + { + LOG_VERBOSE1(_L("Cancel Message Request.\n")); + oUsbOtgDriver.CancelOtgMessageRequest(); + } + +void COtgRoot::otgQueuePeripheralStateRequest(TUint& aPeripheralState, TRequestStatus& aStatus) + { + LOG_VERBOSE1(_L("Queue Peripheral State Request.\n")); + oUsbcClient.AlternateDeviceStatusNotify(aStatus, aPeripheralState); + } + +void COtgRoot::otgCancelPeripheralStateRequest() + { + LOG_VERBOSE1(_L("Cancel Peripheral State Request.\n")); + oUsbcClient.AlternateDeviceStatusNotifyCancel(); + } + +void COtgRoot::otgQueueAConnectionIdleRequest(RUsbOtgDriver::TOtgConnection& aAConnectionIdle, TRequestStatus& aStatus) + { + LOG_VERBOSE1(_L("Queue A Connection Idle Request.\n")); + oUsbOtgDriver.QueueOtgConnectionNotification(aAConnectionIdle, aStatus); + } + +void COtgRoot::otgCancelAConnectionIdleRequest() + { + LOG_VERBOSE1(_L("Cancel A Connection Idle Request.\n")); + oUsbOtgDriver.CancelOtgConnectionNotification(); + } + + +/** otgQueueOtgStateRequest +*/ +void COtgRoot::otgQueueOtgStateRequest(RUsbOtgDriver::TOtgState& aState, TRequestStatus &aStatus) + { + //LOG_FUNC + LOG_VERBOSE2(_L("Queue a State Request %08X.\n"), (TInt)(&aStatus)); + + oUsbOtgDriver.QueueOtgStateRequest(aState, aStatus); + + } + + +/** otgCancelOtgStateRequest +*/ +void COtgRoot::otgCancelOtgStateRequest() + { + LOG_VERBOSE1(_L("Cancel State Request.\n")); + oUsbOtgDriver.CancelOtgStateRequest(); + } + + +/** otgBusRequest +raise VBus (in reality this must only happen when a 'A' is present... and when not present it starts HNP) +*/ +TInt COtgRoot::otgBusRequest() + { + LOG_FUNC + + TInt err(0); + err = oUsbOtgDriver.BusRequest(); + if (err != KErrNone) + { + LOG_FUNCERROR(err) + } + return(err); + } + + +/* call when SRP has been recieved, based on our HNP Enable setting, this will allow HNP. The + * A-device may choose to call BusRequest directly, which will result in a 'short-circuit' role-swap. + */ +TInt COtgRoot::otgBusRespondSRP() + { + LOG_FUNC + TInt err(0); + err = oUsbOtgDriver.BusRespondSrp(); + if (err != KErrNone) + { + LOG_FUNCERROR(err) + } + return(err); + } + + +/** Drop VBus (A-host) +*/ +TInt COtgRoot::otgBusDrop() + { + LOG_FUNC + TInt err(0); + err = oUsbOtgDriver.BusDrop(); + if (err != KErrNone) + { + LOG_FUNCERROR(err) + } + return(err); + } + +/** otgBusClearError +*/ +TInt COtgRoot::otgBusClearError() + { + LOG_FUNC + + TInt err(0); + err = oUsbOtgDriver.BusClearError(); + if (err != KErrNone) + { + LOG_FUNCERROR(err) + } + return(err); + } + + + +void COtgRoot::otgQueueOtgIdPinNotification(RUsbOtgDriver::TOtgIdPin& aPin, TRequestStatus& aStatus) + { + LOG_FUNC + oUsbOtgDriver.QueueOtgIdPinNotification(aPin, aStatus); // the kernel driver populates aPin... + } + + +void COtgRoot::otgCancelOtgIdPinNotification() + { + LOG_FUNC + oUsbOtgDriver.CancelOtgIdPinNotification(); + } + + +void COtgRoot::otgQueueOtgVbusNotification(RUsbOtgDriver::TOtgVbus& aVbus, + TRequestStatus& aStatus + ) + { + LOG_FUNC + oUsbOtgDriver.QueueOtgVbusNotification(aVbus, aStatus); + } + + +void COtgRoot::otgCancelOtgVbusNotification() + { + LOG_FUNC + oUsbOtgDriver.CancelOtgVbusNotification(); + } + + +TBool COtgRoot::otgIdPinPresent() + { + LOG_FUNC + TRequestStatus aStatus; + RUsbOtgDriver::TOtgIdPin aPin; + oUsbOtgDriver.QueueOtgIdPinNotification(aPin, aStatus); // the kernel driver populates aPin... + LOG_VERBOSE2(_L("(sync) ID_PIN=%d\n"), iOTGIdPin); + + oUsbOtgDriver.CancelOtgIdPinNotification(); + // swallow the event + User::WaitForRequest(aStatus); + + if (RUsbOtgDriver::EIdPinAPlug == aPin) // at this stage, the aPin value is known + { + return(ETrue); + } + return(EFalse); + } + + +TBool COtgRoot::otgVbusPresent() + { + LOG_FUNC + TRequestStatus aStatus; + RUsbOtgDriver::TOtgVbus aVBus; + oUsbOtgDriver.QueueOtgVbusNotification(aVBus, aStatus); // the kernel driver populates aPin in a kernel thread... + oUsbOtgDriver.CancelOtgVbusNotification(); + // swallow the event + User::WaitForRequest(aStatus); + + if (RUsbOtgDriver::EVbusHigh == aVBus) // by this stage, the aVBus value is known + { + return(ETrue); + } + return(EFalse); + } + + +TBool COtgRoot::iLoadedLdd = EFalse; +TBool COtgRoot::iFdfActorActive = EFalse; +RProcess COtgRoot::iFdfActorProcess; + +/** static */ +TBool& COtgRoot::LddLoaded() + { + return(iLoadedLdd); + } + + +/** static */ +TBool COtgRoot::SetLoaded(TBool aState) + { + iLoadedLdd = aState; + return(LddLoaded()); + } + +/** static */ +void COtgRoot::OtgEventString( RUsbOtgDriver::TOtgEvent aEvent, TBuf &aDescription) + { + + switch( aEvent ) + { + case RUsbOtgDriver::EEventAPlugInserted: aDescription= _L("A Plug Inserted");break; + case RUsbOtgDriver::EEventAPlugRemoved: aDescription= _L("A Plug Removed"); break; + case RUsbOtgDriver::EEventVbusRaised: aDescription= _L("VBUS Raised"); break; + case RUsbOtgDriver::EEventVbusDropped: aDescription= _L("VBUS Dropped"); break; + case RUsbOtgDriver::EEventSrpReceived: aDescription= _L("SRP Received"); break; + case RUsbOtgDriver::EEventSrpInitiated: aDescription= _L("SRP Initiated"); break; + case RUsbOtgDriver::EEventHnpEnabled: aDescription= _L("HNP Enabled"); break; + case RUsbOtgDriver::EEventHnpDisabled: aDescription= _L("HNP Disabled"); break; + case RUsbOtgDriver::EEventRoleChangedToHost: aDescription= _L("Role->Host"); break; + case RUsbOtgDriver::EEventRoleChangedToDevice: aDescription= _L("Role->Device"); break; + case RUsbOtgDriver::EEventRoleChangedToIdle: aDescription= _L("Role->Idle"); break; + + case RUsbOtgDriver::EEventHnpSupported : aDescription= _L("HNP Supported"); break; + case RUsbOtgDriver::EEventHnpAltSupported: aDescription= _L("Alt-HNP Supp."); break; + case RUsbOtgDriver::EEventBusConnectionBusy: aDescription= _L("Connection Busy"); break; + case RUsbOtgDriver::EEventBusConnectionIdle: aDescription= _L("Connection Idle"); break; + default: aDescription= _L("Unknown"); break; + } + } + +/** static */ +void COtgRoot::OtgStateString( RUsbOtgDriver::TOtgState aState, TBuf &aDescription) + { + + switch( aState ) + { + case RUsbOtgDriver::EStateReset: aDescription= _L("Reset"); break; + case RUsbOtgDriver::EStateAIdle: aDescription= _L("A-Idle"); break; + case RUsbOtgDriver::EStateAHost: aDescription= _L("A-Host"); break; + case RUsbOtgDriver::EStateAPeripheral: aDescription= _L("A-Peripheral"); break; + case RUsbOtgDriver::EStateAVbusError: aDescription= _L("A-VBus Error"); break; + case RUsbOtgDriver::EStateBIdle: aDescription= _L("B-Idle"); break; + case RUsbOtgDriver::EStateBPeripheral: aDescription= _L("B-Peripheral"); break; + case RUsbOtgDriver::EStateBHost: aDescription= _L("B-Host"); break; + default: aDescription= _L("Unknown"); break; + } + } + +/** static */ +void COtgRoot::OtgMessageString( RUsbOtgDriver::TOtgMessage aMessage, TBuf &aDescription) + { + + switch( aMessage ) + { + case RUsbOtgDriver::EEventQueueOverflow: aDescription = _L("Event Queue Overflow"); break; + case RUsbOtgDriver::EStateQueueOverflow: aDescription = _L("State Queue Overflow"); break; + case RUsbOtgDriver::EMessageQueueOverflow: aDescription = _L("Message Queue Overflow"); break; + case RUsbOtgDriver::EMessageBadState: aDescription = _L("Bad State"); break; + case RUsbOtgDriver::EMessageStackNotStarted: aDescription = _L("Stack Not Started"); break; + case RUsbOtgDriver::EMessageVbusAlreadyRaised: aDescription = _L("Vbus Already Raised"); break; + case RUsbOtgDriver::EMessageSrpForbidden: aDescription = _L("SRP Forbidden"); break; + case RUsbOtgDriver::EMessageBusControlProblem: aDescription = _L("Bus Control Problem"); break; + case RUsbOtgDriver::EMessageVbusError: aDescription = _L("Vbus Error"); break; + case RUsbOtgDriver::EMessageSrpTimeout: aDescription = _L("SRP Timeout"); break; + case RUsbOtgDriver::EMessageSrpActive: aDescription = _L("SRP In Use"); break; + // PREQ 1305 messages + case RUsbOtgDriver::EMessageSrpNotPermitted: aDescription = _L("Srp Not Permitted"); break; + case RUsbOtgDriver::EMessageHnpNotPermitted: aDescription = _L("Hnp Not Permitted"); break; + case RUsbOtgDriver::EMessageHnpNotEnabled: aDescription = _L("Hnp Not Enabled"); break; + case RUsbOtgDriver::EMessageHnpNotSuspended: aDescription = _L("HNP not possible, not suspended"); break; + case RUsbOtgDriver::EMessageVbusPowerUpNotPermitted: aDescription = _L("Vbus PowerUp Not Permitted"); break; + case RUsbOtgDriver::EMessageVbusPowerUpError: aDescription = _L("Vbus PowerUp Error"); break; + case RUsbOtgDriver::EMessageVbusPowerDownNotPermitted: aDescription = _L("Vbus PowerDown Not Permitted"); break; + case RUsbOtgDriver::EMessageVbusClearErrorNotPermitted: aDescription = _L("Vbus ClearError Not Permitted"); break; + case RUsbOtgDriver::EMessageHnpNotResponding: aDescription = _L("Not reposnding to HNP"); + case RUsbOtgDriver::EMessageHnpBusDrop: aDescription = _L("VBUS drop during HNP"); + default: aDescription = _L("Unknown"); break; + } + } + +void COtgRoot::PeripheralStateString( TUint aPeripheralState, TBuf &aDescription) + { + if(aPeripheralState & KUsbAlternateSetting) + { + aDescription = _L("Interface Alternate Setting Change"); + } + else + { + switch( aPeripheralState ) + { + case EUsbcDeviceStateUndefined: aDescription = _L("Undefined"); break; + case EUsbcDeviceStateAttached: aDescription = _L("Attached"); break; + case EUsbcDeviceStatePowered: aDescription = _L("Powered"); break; + case EUsbcDeviceStateDefault: aDescription = _L("Default"); break; + case EUsbcDeviceStateAddress: aDescription = _L("Addressed"); break; + case EUsbcDeviceStateConfigured: aDescription = _L("Configured"); break; + case EUsbcDeviceStateSuspended: aDescription = _L("Suspended"); break; + case EUsbcNoState: aDescription = _L("NoState!"); break; + default: aDescription = _L("Unknown"); break; + } + } + } + +void COtgRoot::AConnectionIdleString(RUsbOtgDriver::TOtgConnection aAConnectionIdle, TBuf &aDescription) + { + switch( aAConnectionIdle ) + { + case RUsbOtgDriver::EConnectionBusy: aDescription = _L("Busy"); break; + case RUsbOtgDriver::EConnectionIdle: aDescription = _L("Idle"); break; + case RUsbOtgDriver::EConnectionUnknown: aDescription = _L("Unknown"); break; + default: aDescription = _L("Not recognised");break; + } + } + +TInt COtgRoot::otgActivateFdfActor() + { + if(iFdfActorActive) + { + RDebug::Print(_L("FdfActor already exists!")); + return KErrAlreadyExists; + } + + const TUid KFdfSvrUid={0x10282B48}; + const TUidType fdfActorUid(KNullUid, KNullUid, KFdfSvrUid); + + RDebug::Print(_L("About to activate FDF Actor")); + +// RProcess fdfActorProcess; + TInt err = iFdfActorProcess.Create(_L("t_otgdi_fdfactor.exe"), KNullDesC, fdfActorUid); + + if (err != KErrNone) + { + RDebug::Print(_L("Failed to create FDF Actor, err=%d"),err); + iFdfActorProcess.Close(); + return err; + } + + TRequestStatus stat; + iFdfActorProcess.Rendezvous(stat); + + if (stat!=KRequestPending) + { + RDebug::Print(_L("Failed to commence rendezvous, err=%d"),stat.Int()); + iFdfActorProcess.Kill(0); // abort startup + iFdfActorProcess.Close(); + return stat.Int(); + } + else + { + iFdfActorProcess.Resume(); // logon OK - start the server + } + + User::WaitForRequest(stat); // wait for start or death + if(stat.Int()!=KErrNone) + { + // Wasn't KErrNone, which means that the FDFActor didn't successfully + // start up. We shouldn't proceed with the test we're in. + RDebug::Print(_L("Failed to activate FDF Actor, err=%d"),stat.Int()); + iFdfActorProcess.Close(); + return stat.Int(); + } + + // We rendezvoused(?) with the FDFActor OK, so it is going to suspend + // any devices it sees being attached, and will shut itself down + // when this process signals its Rendezvous (at the end of the test)... + RDebug::Print(_L("Activated FDF Actor")); + iFdfActorActive = ETrue; + + return KErrNone; + } + +void COtgRoot::otgDeactivateFdfActor() + { + if(!iFdfActorActive) + { + RDebug::Print(_L("FdfActor is not running!")); + return; + } + + // If iFdfActorActive is set, the FDF Actor should be waiting to + // rendezvous with us before it shuts down... + // First of all, logon to wait for it to close down properly + TRequestStatus waitForCloseStat; + iFdfActorProcess.Logon(waitForCloseStat); + + // Now, trigger the FDF Actor to close down + + RProcess::Rendezvous(KErrNone); + + // ...and wait for it to go away. + User::WaitForRequest(waitForCloseStat); + test.Printf(_L("T_OTGDI confirms FDF Actor has gone away %d\n"), waitForCloseStat.Int()); + + // Now close our handle, and record that the process is no more... + iFdfActorProcess.Close(); + iFdfActorActive = EFalse; + } + +/** Commonly used step to unload the USB Client Driver +* @return ETrue if the ldd unloaded sucessfully +*/ +TBool COtgRoot::StepUnloadClient() + { + test.Printf(_L("Unload USBCC Client\n")); + + TInt err; + + // Close the Client + + test.Printf(_L("..Close\n")); + oUsbcClient.Close(); + + // Unload the LDD - note the name is *not* the same as for loading + + test.Printf(_L("..Unload\n")); + err = User::FreeLogicalDevice( KUsbDeviceName ); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("Client Unload Fail "), err); + return (EFalse); + } + + + return(ETrue); + } + + +/** Commonly used step to load the USB Client Driver and set up + * a 'useful' default device descriptor set + * @return ETrue if the ldd loaded sucessfully + */ +TBool COtgRoot::StepLoadClient(TUint16 aPID, + TBool aEnableHNP/*=ETrue*/, + TBool aEnableSRP/*=ETrue*/) + { + test.Printf(_L("Load USBCC Client 0x%04x\n"),aPID); + + TInt err; + + // The incoming PID is expected to have a form of 0x0TTT or 0xFTTT + // where 'TTT' is the test number: if the lead is 0xF000 we now + // overlay an 'A' or a 'B' depending on the default role + + if ( ( ( aPID & 0xF000 ) != 0xF000 ) + && ( ( aPID & 0xF000 ) != 0x0000 ) + ) + { + AssertionFailed(KErrAbort, _L("Bad default PID")); + } + + if ( aPID & 0xF000 ) + { + aPID &= 0x0FFF; + + if ( gTestRoleMaster ) + { + // this is the 'B' device + aPID |= 0xB000; + } + else + { + // this is the 'A' device + aPID |= 0xA000; + } + } + + // Load the LDD - note the name is *not* the same as for unload + + test.Printf(_L("..Load LDD\n")); + err = User::LoadLogicalDevice( KUsbcLddFileName ); + if ((err != KErrNone) && (err !=KErrAlreadyExists)) + { + AssertionFailed2(KErrAbort, _L("Client Load Fail "), err); + return (EFalse); + } + + // Open the Client + + test.Printf(_L("..Open LDD\n")); + err = oUsbcClient.Open(0); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("Client Open Fail "), err); + return (EFalse); + } + + // Set up descriptors + + test.Printf(_L("..Setup Descriptors\n")); + + // the OTG descriptor + TBuf8 theOtgDescriptor; + err = oUsbcClient.GetOtgDescriptor(theOtgDescriptor); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("OTG GetDes Fail "), err); + return (EFalse); + } + // modify OTG descriptor based on parameters passed + if (aEnableHNP) + aEnableSRP=ETrue; // Keep the device Legal according to OTG spec 6.4.2 + /*Attribute Fields + D7…2: Reserved (reset to zero) + D1: HNP support + D0: SRP support*/ + TUint8 aByte = theOtgDescriptor[2]; + aByte &= (~0x03); + aByte |= (aEnableSRP? 1 : 0); + aByte |= (aEnableHNP? 2 : 0); + test.Printf(_L("..Change OTG 0x%02X->0x%02X\n"), theOtgDescriptor[2], aByte); + theOtgDescriptor[2] = aByte; + + err = oUsbcClient.SetOtgDescriptor(theOtgDescriptor); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("OTG SetDes Fail "), err); + return (EFalse); + } + + // + + TUsbDeviceCaps d_caps; + err = oUsbcClient.DeviceCaps(d_caps); + TBool softwareConnect; + + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("Client DevCaps Fail "), err); + return (EFalse); + } + + const TInt n = d_caps().iTotalEndpoints; + + softwareConnect = d_caps().iConnect; + test.Printf(_L("..SoftwareConnect = %d\n"),softwareConnect); + + if (n < 2) + { + AssertionFailed2(KErrAbort, _L("Client Endpoints Fail "), err); + return (EFalse); + } + + // Endpoints + TUsbcEndpointData data[KUsbcMaxEndpoints]; + TPtr8 dataptr(reinterpret_cast(data), sizeof(data), sizeof(data)); + err = oUsbcClient.EndpointCaps(dataptr); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("Client EpCaps Fail "), err); + return (EFalse); + } + + // Set up the active interface + TUsbcInterfaceInfoBuf ifc; + TInt ep_found = 0; + TBool foundBulkIN = EFalse; + TBool foundBulkOUT = EFalse; + for (TInt i = 0; i < n; i++) + { + const TUsbcEndpointCaps* const caps = &data[i].iCaps; + const TInt mps = caps->MaxPacketSize(); + if (!foundBulkIN && + (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) == + (KUsbEpTypeBulk | KUsbEpDirIn)) + { + if (!(mps == 64 || mps == 512)) + { + } + // EEndpoint1 is going to be our Tx (IN) endpoint + ifc().iEndpointData[0].iType = KUsbEpTypeBulk; + ifc().iEndpointData[0].iDir = KUsbEpDirIn; + ifc().iEndpointData[0].iSize = mps; + foundBulkIN = ETrue; + if (++ep_found == 2) + break; + } + else if (!foundBulkOUT && + (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) == + (KUsbEpTypeBulk | KUsbEpDirOut)) + { + if (!(mps == 64 || mps == 512)) + { + } + // EEndpoint2 is going to be our Rx (OUT) endpoint + ifc().iEndpointData[1].iType = KUsbEpTypeBulk; + ifc().iEndpointData[1].iDir = KUsbEpDirOut; + ifc().iEndpointData[1].iSize = mps; + foundBulkOUT = ETrue; + if (++ep_found == 2) + break; + } + } + if (ep_found != 2) + { + AssertionFailed2(KErrAbort, _L("Client EpFound Fail "), err); + return (EFalse); + } + + _LIT16(ifcname, "T_OTGDI Test Interface (Default Setting 0)"); + ifc().iString = const_cast(&ifcname); + ifc().iTotalEndpointsUsed = 2; + ifc().iClass.iClassNum = 0xff; // vendor-specific + ifc().iClass.iSubClassNum = 0xff; // vendor-specific + ifc().iClass.iProtocolNum = 0xff; // vendor-specific + + err = oUsbcClient.SetInterface(0, ifc, (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault)); + + if( err != KErrNone ) + { + AssertionFailed2(KErrAbort, _L("Client SetInt Fail "), err); + return (EFalse); + } + + // Set the revised PID + + TBuf8 theDeviceDescriptor; + err = oUsbcClient.GetDeviceDescriptor(theDeviceDescriptor); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("Client GetDes Fail "), err); + return (EFalse); + } + + TUint16 oldPID = ( theDeviceDescriptor[10] ) + + ( theDeviceDescriptor[11] << 8 ); + + theDeviceDescriptor[10] = ( aPID & 0x00FF ); + theDeviceDescriptor[11] = ( aPID & 0xFF00 ) >> 8; + + test.Printf(_L("..Change PID 0x%04X->0x%04X\n"), oldPID, aPID); + + err = oUsbcClient.SetDeviceDescriptor(theDeviceDescriptor); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("Client SetDes Fail "), err); + return (EFalse); + } + + + // Power Up UDC - KErrNotReady is expected + + test.Printf(_L("..Power Up UDC\n")); + + err = oUsbcClient.PowerUpUdc(); + if( err != KErrNotReady ) + { + AssertionFailed2(KErrAbort, _L("PowerUp UDC Fail "), err); + return (EFalse); + } + + // Connect to Host + + test.Printf(_L("..Connect to Host\n")); + + err = oUsbcClient.DeviceConnectToHost(); + if( err != KErrNone ) + { + AssertionFailed2(KErrAbort, _L("Host Connect Fail "), err); + return (EFalse); + } + + // Default no-problem return + + return(ETrue); + } + + +/** Commonly used steps to control D+ connect/disconnect + * the device to/from the host + */ +TBool COtgRoot::StepDisconnect() + { + test.Printf(_L("Disconnect from Host\n")); + + TInt err; + + err = oUsbcClient.DeviceDisconnectFromHost(); + if( err != KErrNone ) + { + AssertionFailed2(KErrAbort, _L("Host Disconnect Fail "), err); + return (EFalse); + } + + // Default no-problem return + + return(ETrue); + } + +TBool COtgRoot::StepConnect() + { + test.Printf(_L("Connect to Host\n")); + + TInt err; + + err = oUsbcClient.DeviceConnectToHost(); + if( err != KErrNone ) + { + AssertionFailed2(KErrAbort, _L("Host Connect Fail "), err); + return (EFalse); + } + + // Default no-problem return + + return(ETrue); + } + + +/** Commonly used step to load the USB Client Driver and set up + * a High-Speed electrical test VID/PID pair + * @return ETrue if the ldd loaded sucessfully + */ +TBool COtgRoot::StepChangeVidPid(TUint16 aVID, TUint16 aPID) + + { + test.Printf(_L("Load USBCC HS Test Client 0x%04x/0x%04x\n"),aVID,aPID); + + TInt err; + + // Set the revised VID/PID pair + + TBuf8 theDeviceDescriptor; + err = oUsbcClient.GetDeviceDescriptor(theDeviceDescriptor); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("Client GetDes Fail "), err); + return (EFalse); + } + + TUint16 oldVID = ( theDeviceDescriptor[8] ) + + ( theDeviceDescriptor[9] << 8 ); + + theDeviceDescriptor[8] = ( aVID & 0x00FF ); + theDeviceDescriptor[9] = ( aVID & 0xFF00 ) >> 8; + + test.Printf(_L("..Change VID 0x%04X->0x%04X\n"), oldVID, aVID); + + TUint16 oldPID = ( theDeviceDescriptor[10] ) + + ( theDeviceDescriptor[11] << 8 ); + + theDeviceDescriptor[10] = ( aPID & 0x00FF ); + theDeviceDescriptor[11] = ( aPID & 0xFF00 ) >> 8; + + test.Printf(_L("..Change PID 0x%04X->0x%04X\n"), oldPID, aPID); + + err = oUsbcClient.SetDeviceDescriptor(theDeviceDescriptor); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("Client SetDes Fail "), err); + return (EFalse); + } + + // Default no-problem return + + return(ETrue); + } + + +/** Commonly used step to set a flag that will cause the + OPT test mode to be activated when the stacks are + started +*/ +void COtgRoot::StepSetOptActive() + { + iOptActive = ETrue; + } + + +/** Commonly used step to unload the ldd and shut it down +*@return ETrue if the ldd unloaded sucessfully +*/ +TBool COtgRoot::StepUnloadLDD() + { + test.Printf(_L("Unload otg LDD (implicit Stop() + Close()) \n")); + + LOG_VERBOSE1(_L(" Stop OTG+Host Stack\n")); + otgStopStacks(); + otgClose(); + + LOG_VERBOSE1(_L(" Unload\n")); + otgUnloadLdd(); + + iOptActive = EFalse; // retain the OTGDI behavour to clears this flag when client shuts + if (LddLoaded()) + return(EFalse); + return(ETrue); + } + + +/** StepLoadLDD - utility method : load the LDD, open it and init the stacks + a commonly used test step */ +TBool COtgRoot::StepLoadLDD() + { + TInt err; + + LOG_VERBOSE1(_L("Load otg LDD\n")); + err = otgLoadLdd(); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("Loading LDD failed "), err); + return (EFalse); + } + + LOG_VERBOSE1(_L("Open the LDD session\n")); + err = otgOpen(); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("Open LDD session failed "), err); + return (EFalse); + } + + if ( iOptActive ) + { + test.Printf(_L("Activate OPT Test Mode\n")); + err = otgActivateOptTestMode(); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("OPT Activate failed "), err); + return (EFalse); + } + } + + test.Printf(_L("Start OTG+Host Stack\n")); + err = otgStartStacks(); + if (err != KErrNone) + { + AssertionFailed2(KErrAbort, _L("Start stack failed "), err); + return (EFalse); + } + + // DS - Temporarily adding .1 second delay in here to beat the race + // condition to be fixed as part of third part USB HOST/OTG stack issue 60761 + User::After(100000); + + return(ETrue); + } + +void COtgRoot::SetMaxPowerToL(TUint16 aVal) + { + + TBuf8 buf; + + oUsbcClient.GetConfigurationDescriptor(buf); + + aVal %= 500; + + buf[8] = (TUint8)(aVal / 2); + + oUsbcClient.SetConfigurationDescriptor(buf); + + } + +void COtgRoot::GetMaxPower(TUint16& aVal) + { + TBuf8 buf; + + oUsbcClient.GetConfigurationDescriptor(buf); + + aVal = buf[8] * 2; + } + +