diff -r 000000000000 -r bde4ae8d615e os/kernelhwsrv/kerneltest/e32test/usb/t_usb_device/src/activecontrol.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/kernelhwsrv/kerneltest/e32test/usb/t_usb_device/src/activecontrol.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,1648 @@ +// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test/usb/t_usb_device/src/activecontrol.cpp +// USB Test Program T_USB_DEVICE, functional part. +// Device-side part, to work against T_USB_HOST running on the host. +// +// + + +#include "general.h" +#include "usblib.h" // Helpers +#include "config.h" +#include "activecontrol.h" +#include "apitests.h" +#include "activerw.h" + +void StartMassStorage(RDEVCLIENT* aPort); +void StopMassStorage(RDEVCLIENT* aPort); + +enum Ep0Requests + { + EStop = 0x1, + EVersion = 0x10, + ETestParam = 0x20, + ETestResult = 0x30, + ETestFail = 0x40, + ETestConnect = 0x50, + ETestDisconnect = 0x60, + ETestMassStorage = 0x70, + ETestIdleCounter = 0x80, + }; + +extern RTest test; +extern TBool gVerbose; +extern TBool gSkip; +extern TBool gTempTest; +extern TBool gStopOnFail; +extern TBool gAltSettingOnNotify; +extern TInt gSoakCount; +extern CActiveRW* gRW[KMaxConcurrentTests]; // the USB read/write active object +extern IFConfigPtr gInterfaceConfig [128] [KMaxInterfaceSettings]; +extern TInt gActiveTestCount; +#ifdef USB_SC +extern RChunk gChunk; +#endif + +TInt firstBulkOutEndpoint = -1; + +_LIT(KTestIdleCounterChunkName, "TestIdleCounter"); +_LIT(KTestIdleCounterPanic, "IdleCounter"); + +enum TTestIdleCounterPanic + { + ETestIdleCounterWrongCommand + }; + +enum TTestIdleCounterCommand + { + ETestIdleCounterDoNothing, + ETestIdleCounterReset, + ETestIdleCounterClose + }; + +struct TTestIdleCounter + { + volatile TInt64 iCounter; + volatile TTestIdleCounterCommand iCommand; + }; + +TInt IdleCounterThread(TAny*) + { + TInt r; + // + RThread().SetPriority(EPriorityAbsoluteVeryLow); + // + RChunk chunk; + r = chunk.CreateGlobal(KTestIdleCounterChunkName, + sizeof(struct TTestIdleCounter), + sizeof(struct TTestIdleCounter) + 1); + if (r == KErrNone) + { + struct TTestIdleCounter* counter = (struct TTestIdleCounter*) chunk.Base(); + counter->iCounter = 0; + counter->iCommand = ETestIdleCounterDoNothing; + // + FOREVER + { + TInt command = counter->iCommand; + if (command == ETestIdleCounterReset) + { + counter->iCounter = 0; + counter->iCommand = ETestIdleCounterDoNothing; + } + else if (command == ETestIdleCounterClose) + { + break; + } + else if (command != ETestIdleCounterDoNothing) + { + RThread().Panic(KTestIdleCounterPanic, ETestIdleCounterWrongCommand); + } + // + counter->iCounter++; + } + // + chunk.Close(); + } + return r; + } + +// +// --- class CActiveControl --------------------------------------------------------- +// + +CActiveControl::CActiveControl(CConsoleBase* aConsole, TDes * aConfigFile, TDes * aScriptFile) + : CActive(EPriorityNormal), + iConsole(aConsole), + iSoftwareConnect(EFalse), + iHighSpeed(EFalse), + iConfigFileName(aConfigFile), + iScriptFileName(aScriptFile), + iEp0PacketSize(0) + {} + + +CActiveControl* CActiveControl::NewLC(CConsoleBase* aConsole, TDes * aConfigFile, TDes * aScriptFile) + { + CActiveControl* self = new (ELeave) CActiveControl(aConsole, aConfigFile, aScriptFile); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + + +CActiveControl* CActiveControl::NewL(CConsoleBase* aConsole, TDes * aConfigFile, TDes * aScriptFile) + { + CActiveControl* self = NewLC(aConsole, aConfigFile, aScriptFile); + CleanupStack::Pop(); + return self; + } + + +void CActiveControl::ConstructL() + { + CActiveScheduler::Add(this); + TInt r; + + User::LeaveIfError(iFs.Connect()); + + test.Start (_L("Configuration")); + + test_Compare(iConfigFileName->Length(),!=,0); + + iTimer.CreateLocal(); + iPending = EPendingNone; + + test.Next (_L("Open configuration file")); + // set the session path to use the ROM if no drive specified + r=iFs.SetSessionPath(_L("Z:\\test\\")); + test_KErrNone(r); + + r = iConfigFile.Open(iFs, * iConfigFileName, EFileShareReadersOnly | EFileStreamText | EFileRead); + test_KErrNone(r); + TUSB_VERBOSE_PRINT1("Configuration file %s Opened successfully", iConfigFileName->PtrZ()); + + test.Next (_L("Process configuration file")); + test(ProcessConfigFile (iConfigFile,iConsole,&iLddPtr)); + + iConfigFile.Close(); + + test.Next (_L("LDD in configuration file")); + test_NotNull(iLddPtr); + + LDDConfigPtr lddPtr = iLddPtr; + TInt nextPort = 0; + while (lddPtr != NULL) + { + // Load logical driver (LDD) + // (There's no physical driver (PDD) with USB: it's a kernel extension DLL which + // was already loaded at boot time.) + test.Next (_L("Loading USB LDD")); + TUSB_VERBOSE_PRINT1("Loading USB LDD ",lddPtr->iName.PtrZ()); + r = User::LoadLogicalDevice(lddPtr->iName); + test(r == KErrNone || r == KErrAlreadyExists); + + IFConfigPtr ifPtr = lddPtr->iIFPtr; + + test.Next (_L("Opening Channels")); + for (TInt portNumber = nextPort; portNumber < nextPort+lddPtr->iNumChannels; portNumber++) + { + test_Compare(lddPtr->iNumChannels,>,0); + + // Open USB channel + r = iPort[portNumber].Open(0); + test_KErrNone(r); + TUSB_VERBOSE_PRINT("Successfully opened USB port"); + + // Query the USB device/Setup the USB interface + if (portNumber == nextPort) + { + // Change some descriptors to contain suitable values + SetupDescriptors(lddPtr, &iPort[portNumber]); + } + + if (portNumber == 0) + { + QueryUsbClientL(lddPtr, &iPort[portNumber]); + } + + test_NotNull(ifPtr); + + IFConfigPtr defaultIfPtr = ifPtr; + SetupInterface(&ifPtr,portNumber); + + #ifdef USB_SC + RChunk *tChunk = &gChunk; + test_KErrNone(iPort[portNumber].FinalizeInterface(tChunk)); + #endif + + // allocate endpoint DMA and double buffering for all endpoints on default interface + for (TUint8 i = 1; i <= defaultIfPtr->iInfoPtr->iTotalEndpointsUsed; i++) + { + defaultIfPtr->iEpDMA[i-1] ? AllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i); + #ifndef USB_SC + defaultIfPtr->iEpDoubleBuff[i-1] ? AllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i); + #endif + } + + } + + iTotalChannels += lddPtr->iNumChannels; + nextPort += lddPtr->iNumChannels; + lddPtr = lddPtr->iPtrNext; + } + + TUSB_VERBOSE_PRINT("All Interfaces and Alternate Settings successfully set up"); + + test.Next (_L("Start Idle Counter Thread")); + r = iIdleCounterThread.Create(_L("IdleCounter"), IdleCounterThread, KDefaultStackSize, KMinHeapSize, KMinHeapSize, NULL); + test_KErrNone(r); + iIdleCounterThread.Resume(); + // Allow some time for low-priority counter process + User::After(100000); // 0.1 second + r = iIdleCounterChunk.OpenGlobal(KTestIdleCounterChunkName, EFalse); + test_KErrNone(r); + iIdleCounter = (struct TTestIdleCounter*) iIdleCounterChunk.Base(); + test_NotNull(iIdleCounter); + // Allow some time for low-priority counter process + User::After(100000); // 0.1 second + TInt64 val1 = iIdleCounter->iCounter; + User::After(1000000); // 1 second + TInt64 val2 = iIdleCounter->iCounter; + TUSB_PRINT1("Idle Counter when test inactive: %Ldinc/ms", (val2 - val1) / 1000); + + test.Next (_L("Enumeration...")); + r = ReEnumerate(); + test_KErrNone(r); + + TUSB_VERBOSE_PRINT("Device successfully re-enumerated\n"); + + + if (iLddPtr->iHighSpeed && !gSkip) + { + test.Next (_L("High Speed")); + test(iHighSpeed); + } + + test.Next (_L("Create Notifiers")); + for (TInt portNumber = 0; portNumber < iTotalChannels; portNumber++) + { + + // Create device state active object + iDeviceStateNotifier[portNumber] = CActiveDeviceStateNotifier::NewL(iConsole, &iPort[portNumber], portNumber); + test_NotNull(iDeviceStateNotifier[portNumber]); + iDeviceStateNotifier[portNumber]->Activate(); + TUSB_VERBOSE_PRINT("Created device state notifier"); + + // Create endpoint stall status active object + iStallNotifier[portNumber] = CActiveStallNotifier::NewL(iConsole, &iPort[portNumber]); + test_NotNull(iStallNotifier[portNumber]); + iStallNotifier[portNumber]->Activate(); + TUSB_VERBOSE_PRINT("Created stall notifier"); + + TestInvalidSetInterface (&iPort[portNumber],iNumInterfaceSettings[portNumber]); + TestInvalidReleaseInterface (&iPort[portNumber],iNumInterfaceSettings[portNumber]); + + } + + test.Next (_L("Endpoint Zero Max Packet Sizes")); + TUint ep0Size = iPort[0].EndpointZeroMaxPacketSizes(); + switch (ep0Size) + { + case KUsbEpSize8 : + iEp0PacketSize = 8; + break; + + case KUsbEpSize16 : + iEp0PacketSize = 16; + break; + + case KUsbEpSize32 : + iEp0PacketSize = 32; + break; + + case KUsbEpSize64 : + iEp0PacketSize = 64; + break; + + default: + iEp0PacketSize = 0; + break; + } + test_Compare(iEp0PacketSize,>,0); + + test.Next (_L("Set Device Control")); + r = iPort[0].SetDeviceControl(); + test_KErrNone(r); + + #ifdef USB_SC + r = iPort[0].OpenEndpoint(iEp0Buf,0); + test_KErrNone(r); + #endif + + test.End(); + + } + +void CActiveControl::ReConnect() + { + TInt r; + + test.Start (_L("Reconnecting USB")); + LDDConfigPtr lddPtr = iLddPtr; + TInt nextPort = 0; + while (lddPtr != NULL) + { + IFConfigPtr ifPtr = lddPtr->iIFPtr; + + test.Next (_L("Opening Channels")); + for (TInt portNumber = nextPort; portNumber < nextPort+lddPtr->iNumChannels; portNumber++) + { + // Open USB channel + r = iPort[portNumber].Open(0); + test_KErrNone(r); + TUSB_VERBOSE_PRINT("Successfully opened USB port"); + + // Query the USB device/Setup the USB interface + if (portNumber == nextPort) + { + // Change some descriptors to contain suitable values + SetupDescriptors(lddPtr, &iPort[portNumber]); + } + + IFConfigPtr defaultIfPtr = ifPtr; + SetupInterface(&ifPtr,portNumber); + + #ifdef USB_SC + RChunk *tChunk = &gChunk; + test_KErrNone(iPort[portNumber].FinalizeInterface(tChunk)); + #endif + + // allocate endpoint DMA and double buffering for all endpoints on default interface + for (TUint8 i = 1; i <= defaultIfPtr->iInfoPtr->iTotalEndpointsUsed; i++) + { + defaultIfPtr->iEpDMA[i-1] ? AllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i); + #ifndef USB_SC + defaultIfPtr->iEpDoubleBuff[i-1] ? AllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i); + #endif + } + } + + nextPort += lddPtr->iNumChannels; + lddPtr = lddPtr->iPtrNext; + } + + TUSB_VERBOSE_PRINT("All Interfaces and Alternate Settings successfully set up"); + + test.Next (_L("Enumeration...")); + r = ReEnumerate(); + test_KErrNone(r); + + TUSB_VERBOSE_PRINT("Device successfully re-enumerated\n"); + + for (TInt portNumber = 0; portNumber < iTotalChannels; portNumber++) + { + // Create device state active object + iDeviceStateNotifier[portNumber] = CActiveDeviceStateNotifier::NewL(iConsole, &iPort[portNumber], portNumber); + test_NotNull(iDeviceStateNotifier[portNumber]); + iDeviceStateNotifier[portNumber]->Activate(); + TUSB_VERBOSE_PRINT("Created device state notifier"); + + // Create endpoint stall status active object + iStallNotifier[portNumber] = CActiveStallNotifier::NewL(iConsole, &iPort[portNumber]); + test_NotNull(iStallNotifier[portNumber]); + iStallNotifier[portNumber]->Activate(); + TUSB_VERBOSE_PRINT("Created stall notifier"); + + if (portNumber == 0) + { + test.Next (_L("Set Device Control")); + r = iPort[portNumber].SetDeviceControl(); + test_KErrNone(r); + + #ifdef USB_SC + r = iPort[portNumber].OpenEndpoint(iEp0Buf,0); + test_KErrNone(r); + #endif + + } + } + + test.End(); + } + +void CActiveControl::SetupInterface(IFConfigPtr* aIfPtr, TInt aPortNumber) + { + test.Start (_L("Setup Interface")); + + // first of all set the default interface + TUSB_PRINT2 ("Set Default Interface with %d endpoints bandwidth 0x%x",(*aIfPtr)->iInfoPtr->iTotalEndpointsUsed,(*aIfPtr)->iBandwidthIn | (*aIfPtr)->iBandwidthOut); + #ifdef USB_SC + TUsbcScInterfaceInfoBuf ifc = *((*aIfPtr)->iInfoPtr); + TInt r = iPort[aPortNumber].SetInterface(0, ifc); + #else + TUsbcInterfaceInfoBuf ifc = *((*aIfPtr)->iInfoPtr); + TInt r = iPort[aPortNumber].SetInterface(0, ifc, (*aIfPtr)->iBandwidthIn | (*aIfPtr)->iBandwidthOut); + #endif + test_KErrNone(r); + + TBuf8 ifDescriptor; + r = iPort[aPortNumber].GetInterfaceDescriptor(0, ifDescriptor); + test_KErrNone(r); + + // Check the interface descriptor + test(ifDescriptor[KIfcDesc_SettingOffset] == 0 && ifDescriptor[KIfcDesc_NumEndpointsOffset] == (*aIfPtr)->iInfoPtr->iTotalEndpointsUsed && + ifDescriptor[KIfcDesc_ClassOffset] == (*aIfPtr)->iInfoPtr->iClass.iClassNum && + ifDescriptor[KIfcDesc_SubClassOffset] == (*aIfPtr)->iInfoPtr->iClass.iSubClassNum && + ifDescriptor[KIfcDesc_ProtocolOffset] == (*aIfPtr)->iInfoPtr->iClass.iProtocolNum); + + if ((*aIfPtr)->iNumber != 0 && ifDescriptor[KIfcDesc_NumberOffset] != (*aIfPtr)->iNumber) + { + ifDescriptor[KIfcDesc_NumberOffset] = (*aIfPtr)->iNumber; + r = iPort[aPortNumber].SetInterfaceDescriptor(0, ifDescriptor); + test_KErrNone(r); + } + else + { + (*aIfPtr)->iNumber = ifDescriptor[KIfcDesc_NumberOffset]; + } + TUint8 interfaceNumber = (*aIfPtr)->iNumber; + TUSB_PRINT1 ("Interface Number %d",interfaceNumber); + + // Check all endpoint descriptors + TBuf8 epDescriptor; + for (TUint i = 0; i < (*aIfPtr)->iInfoPtr->iTotalEndpointsUsed; i++) + { + if (!gSkip) + { + TestEndpointDescriptor (&iPort[aPortNumber],0,i+1,(*aIfPtr)->iInfoPtr->iEndpointData[i]); + + } + + if (firstBulkOutEndpoint < 0 && ((*aIfPtr)->iInfoPtr->iEndpointData[i].iDir & KUsbEpDirOut) && + (*aIfPtr)->iInfoPtr->iEndpointData[i].iType == KUsbEpTypeBulk) + { + firstBulkOutEndpoint = i+1; + } + } + + TUSB_PRINT1 ("Interface number is %d",interfaceNumber); + (*aIfPtr)->iPortNumber = aPortNumber; + gInterfaceConfig [interfaceNumber] [0] = *aIfPtr; + + TInt alternateNumber = 1; + // check for any alternatate interfaces and set any that are found + * aIfPtr = (*aIfPtr)->iPtrNext; + if (* aIfPtr != NULL) + { + test(SupportsAlternateInterfaces()); + + IFConfigPtr ifPtr = *aIfPtr; + while (ifPtr != NULL) + { + if (ifPtr->iAlternateSetting) + { + ifc = *(ifPtr->iInfoPtr); + #ifdef USB_SC + TUSB_PRINT2 ("Set Alternate Interface Setting %d with %d endpoints",alternateNumber,ifPtr->iInfoPtr->iTotalEndpointsUsed); + r = iPort[aPortNumber].SetInterface(alternateNumber, ifc); + #else + TUSB_PRINT3 ("Set Alternate Interface Setting %d with %d endpoints bandwidth 0x%x",alternateNumber,ifPtr->iInfoPtr->iTotalEndpointsUsed,ifPtr->iBandwidthIn | iLddPtr->iIFPtr->iBandwidthOut); + r = iPort[aPortNumber].SetInterface(alternateNumber, ifc, ifPtr->iBandwidthIn | iLddPtr->iIFPtr->iBandwidthOut); + #endif + test_KErrNone(r); + + r = iPort[aPortNumber].GetInterfaceDescriptor(alternateNumber, ifDescriptor); + test_KErrNone(r); + + // Check the interface descriptor + test(ifDescriptor[KIfcDesc_SettingOffset] == alternateNumber && ifDescriptor[KIfcDesc_NumEndpointsOffset] == (*aIfPtr)->iInfoPtr->iTotalEndpointsUsed && + ifDescriptor[KIfcDesc_ClassOffset] == (*aIfPtr)->iInfoPtr->iClass.iClassNum && + ifDescriptor[KIfcDesc_SubClassOffset] == (*aIfPtr)->iInfoPtr->iClass.iSubClassNum && + ifDescriptor[KIfcDesc_ProtocolOffset] == (*aIfPtr)->iInfoPtr->iClass.iProtocolNum); + + // Check all endpoint descriptors + for (TUint i = 0; i < ifPtr->iInfoPtr->iTotalEndpointsUsed; i++) + { + TInt desc_size; + r = iPort[aPortNumber].GetEndpointDescriptorSize(alternateNumber, i+1, desc_size); + test_KErrNone(r); + test_Equal(KUsbDescSize_Endpoint + (*aIfPtr)->iInfoPtr->iEndpointData[i].iExtra,static_cast(desc_size)); + + r = iPort[aPortNumber].GetEndpointDescriptor(alternateNumber, i+1, epDescriptor); + test_KErrNone(r); + + test((((*aIfPtr)->iInfoPtr->iEndpointData[i].iDir & KUsbEpDirIn) && (epDescriptor[KEpDesc_AddressOffset] & 0x80) || + !((*aIfPtr)->iInfoPtr->iEndpointData[i].iDir & KUsbEpDirIn) && !(epDescriptor[KEpDesc_AddressOffset] & 0x80)) && + EpTypeMask2Value((*aIfPtr)->iInfoPtr->iEndpointData[i].iType) == (TUint)(epDescriptor[KEpDesc_AttributesOffset] & 0x03) && + (*aIfPtr)->iInfoPtr->iEndpointData[i].iInterval == epDescriptor[KEpDesc_IntervalOffset]); + + + if (!gSkip && (*aIfPtr)->iInfoPtr->iEndpointData[i].iExtra) + { + test.Next(_L("Extended Endpoint Descriptor Manipulation")); + TUint8 addr = 0x85; // bogus address + if (epDescriptor[KEpDesc_SynchAddressOffset] == addr) + addr++; + epDescriptor[KEpDesc_SynchAddressOffset] = addr; + r = iPort[aPortNumber].SetEndpointDescriptor(alternateNumber, i+1, epDescriptor); + test_KErrNone(r); + + TBuf8 descriptor2; + r = iPort[aPortNumber].GetEndpointDescriptor(alternateNumber, i+1, descriptor2); + test_KErrNone(r); + + test.Next(_L("Compare endpoint descriptor with value set")); + r = descriptor2.Compare(epDescriptor); + test_KErrNone(r); + } + } + + + // if no error move on to the next interface + ifPtr->iPortNumber = aPortNumber; + ifPtr->iNumber = interfaceNumber; + gInterfaceConfig [interfaceNumber] [alternateNumber] = ifPtr; + + alternateNumber++; + ifPtr = ifPtr->iPtrNext; + * aIfPtr = ifPtr; + } + else + { + ifPtr = NULL; + } + } + } + iNumInterfaceSettings[aPortNumber] = alternateNumber; + if (!gSkip) + { + TestInvalidSetInterface (&iPort[aPortNumber],iNumInterfaceSettings[aPortNumber]); + TestInvalidReleaseInterface (&iPort[aPortNumber],iNumInterfaceSettings[aPortNumber]); + + TestDescriptorManipulation(iLddPtr->iHighSpeed,&iPort[aPortNumber],alternateNumber); + TestOtgExtensions(&iPort[aPortNumber]); + TestEndpoint0MaxPacketSizes(&iPort[aPortNumber]); + } + + test.End(); + } + + +CActiveControl::~CActiveControl() + { + TUSB_PRINT("CActiveControl::~CActiveControl()"); + + Cancel(); + + iTimer.Close(); + + // delete interfaces + while (iLddPtr->iIFPtr) + { + IFConfigPtr* ifPtrPtr = & iLddPtr->iIFPtr; + while ((*ifPtrPtr)->iPtrNext) + { + ifPtrPtr = &(*ifPtrPtr)->iPtrNext; + } + delete (*ifPtrPtr)->iInfoPtr->iString; + delete (*ifPtrPtr)->iInfoPtr; + delete (*ifPtrPtr); + * ifPtrPtr = NULL; + } + + while (iLddPtr) + { + LDDConfigPtr* lddPtrPtr = &iLddPtr; + while ((*lddPtrPtr)->iPtrNext) + { + lddPtrPtr = &(*lddPtrPtr)->iPtrNext; + } + delete (*lddPtrPtr)->iManufacturer; + delete (*lddPtrPtr)->iProduct; + delete (*lddPtrPtr)->iSerialNumber; + delete (*lddPtrPtr); + * lddPtrPtr = NULL; + } + + iFs.Close(); + } + +void CActiveControl::DoCancel() + { + TUSB_VERBOSE_PRINT("CActiveControl::DoCancel()"); + iConsole->ReadCancel(); + } + +void CActiveControl::SetMSFinished(TBool aState) + { + if (aState) + { + if (iPending != EPendingEject) + { + iPending = EPendingEject; + iTimer.After(iStatus,KMSFinishedDelay); + if (!IsActive()) + { + SetActive(); + } + } + } + else + { + if (iPending == EPendingEject) + { + iPending = EPendingCancel; + iTimer.Cancel(); + } + } + } + +void CActiveControl::RequestEp0ControlPacket() + { + TUSB_VERBOSE_PRINT("CActiveControl::RequestEp0ControlPacket()"); + // A request is issued to read a packet for endpoint 0 + __ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 660)); + #ifdef USB_SC + TInt r = 0; + do + { + r = iEp0Buf.GetBuffer (iEp0Packet,iEp0Size,iEp0Zlp,iStatus); + TUSB_VERBOSE_PRINT4("Get Buffer Return code %d Status %d PacketPtr 0x%x Size %d", r, iStatus.Int(),iEp0Packet,iEp0Size); + test_Value(r, (r == KErrNone) || (r == KErrCompletion) || (r == TEndpointBuffer::KStateChange) || (r == KErrAlternateSettingChanged)); + if (r == KErrCompletion) + { + // ignore anything except a setup packet + if ((TInt)iEp0Size == KSetupPacketSize) + { + iEp0SetUpPacket.Copy((TUint8 *)iEp0Packet,iEp0Size); + r = ProcessEp0ControlPacket(); + } + } + else + { + if (r == KErrNone) + { + iPending = EPendingEp0Read; + SetActive(); + } + } + } + while ((r == KErrCompletion) || (r == TEndpointBuffer::KStateChange) || (r == KErrAlternateSettingChanged)); + #else + iPort[0].ReadPacket(iStatus,EEndpoint0, iEp0SetUpPacket,KSetupPacketSize); + iPending = EPendingEp0Read; + SetActive(); + #endif + } + +void CActiveControl::RunL() + { + TInt r = KErrNone; + + TUSB_VERBOSE_PRINT("CActiveControl::RunL()"); + + switch (iPending) + { + case EPendingNone : + break; + + case EPendingEp0Read : + iPending = EPendingNone; + if (iStatus != KErrNone) + { + TUSB_PRINT1("ActiveControl::Error %d in Ep0 Read Packet", iStatus.Int()); + test(EFalse); + } + #ifdef USB_SC + // for shared chunks this means that data is available in the buffer + // but the data has yet to be transferred to a local buffer + RequestEp0ControlPacket(); + #else + if (ProcessEp0ControlPacket() == KErrCompletion) + RequestEp0ControlPacket(); + #endif + break; + + case EPendingTimer : + iPending = EPendingNone; + if (iStatus != KErrNone) + { + TUSB_PRINT1("ActiveControl::Error %d in Connection Timer Delay", iStatus.Int()); + test(EFalse); + } + r = iPort[0].DeviceConnectToHost(); + test_KErrNone (r); + + test.End(); + + RequestEp0ControlPacket(); + break; + + case EPendingEject : + iPending = EPendingNone; + if (iStatus != KErrNone) + { + TUSB_PRINT1("ActiveControl::Error %d in Eject Timer Delay", iStatus.Int()); + test(EFalse); + } + StopMassStorage(&iPort[0]); + #ifdef USB_SC + iEp0Buf.Close(); + #endif + ReConnect(); + + RequestEp0ControlPacket(); + break; + + case EPendingCancel : + iPending = EPendingNone; + if (iStatus != KErrNone && iStatus != KErrCancel) + { + TUSB_PRINT1("ActiveControl::Error %d in Eject Timer Delay", iStatus.Int()); + test(EFalse); + } + } + + } + +TInt CActiveControl::ProcessEp0ControlPacket() + { + TUint16 value = *reinterpret_cast(&iEp0SetUpPacket[KUsb_Ep0wValueOffset]); + TUint16 index = *reinterpret_cast(&iEp0SetUpPacket[KUsb_Ep0wIndexOffset]); + TUint16 length= *reinterpret_cast(&iEp0SetUpPacket[KUsb_Ep0wLengthOffset]); + TUSB_VERBOSE_PRINT3("ProcessEp0ControlPacket length 0x%x value 0x%x index 0x%x",length,value,index); + TRequestStatus ep0Status; + TUint8 host_ver_major; + TUint8 host_ver_minor; + TUint8 host_ver_micro; + TUint8 usbio_ver_major; + TUint8 usbio_ver_minor; + #ifndef USB_SC + TBuf8 ep0DataPacket; + #endif + TestParamPtr tpPtr; + TBool firstSettingThread = (index & KFirstSettingThreadMask) ? ETrue : EFalse; + TBool lastSettingThread = (index & KLastSettingThreadMask) ? ETrue : EFalse; + index &= ~(KFirstSettingThreadMask | KLastSettingThreadMask); + CActiveRW* pActiveRW; + TInt r; + TBool sendStatus; + + if (((iEp0SetUpPacket[KUsb_Ep0RequestTypeOffset] & KUsbRequestType_DestMask) == KUsbRequestType_DestDevice) && + ((iEp0SetUpPacket[KUsb_Ep0RequestTypeOffset] & KUsbRequestType_TypeMask) == KUsbRequestType_TypeClass)) + { + TUSB_VERBOSE_PRINT("Received Device Directed setup packet"); + if ((iEp0SetUpPacket[KUsb_Ep0RequestTypeOffset] & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev) + { + iEp0DataBuffer.SetLength(0); + while (iEp0DataBuffer.Length() < length) + { + TUSB_VERBOSE_PRINT("Reading Ep0 data packet"); + #ifdef USB_SC + r = iEp0Buf.GetBuffer (iEp0Packet,iEp0Size,iEp0Zlp,ep0Status); + test_Value(r, r == KErrNone || r == KErrCompletion || (r == KErrAlternateSettingChanged)); + while (r == KErrNone) + { + TUSB_VERBOSE_PRINT("Waiting for Ep0 data packet"); + User::WaitForRequest(ep0Status); + test_KErrNone(ep0Status.Int()); + r = iEp0Buf.GetBuffer (iEp0Packet,iEp0Size,iEp0Zlp,ep0Status); + test_Value(r, r == KErrNone || r == KErrCompletion || (r == KErrAlternateSettingChanged)); + } + TUSB_VERBOSE_PRINT1("Ep0 data packet - size %d",iEp0Size); + iEp0DataBuffer.Append((TUint8 *)iEp0Packet,iEp0Size); + #else + TUint16 packetLength = Min(length-iEp0DataBuffer.Length(),iEp0PacketSize); + iPort[0].ReadPacket(ep0Status, EEndpoint0, ep0DataPacket, packetLength); + User::WaitForRequest(ep0Status); + if (ep0Status == KErrNone) + { + iEp0DataBuffer.Append(ep0DataPacket); + } + else + { + TUSB_PRINT1("ActiveControl::Error %d in Ep0 Read Data Packet", ep0Status.Int()); + test(EFalse); + return KErrNone; + } + #endif + } + TUSB_VERBOSE_PRINT4("Setup ToDevice Type %d length %d value %d index %d",iEp0SetUpPacket[KUsb_Ep0RequestOffset],length,value,index); + sendStatus = ETrue; + switch (iEp0SetUpPacket[KUsb_Ep0RequestOffset]) + { + case EStop : + // send this now as the port will be disconnected + sendStatus = EFalse; + r = iPort[0].SendEp0StatusPacket(); + test_KErrNone(r); + + if (value && firstBulkOutEndpoint > 0) + { + PrintHostLog(); + } + + for (TInt portNumber = 0; portNumber < iTotalChannels; portNumber++) + { + // base class cancel -> calls our DoCancel + delete iDeviceStateNotifier[portNumber]; + delete iStallNotifier[portNumber]; + if (portNumber == 0) + { + r = iPort[portNumber].RemoveStringDescriptor(stridx1); + if (r != KErrNone) + { + TUSB_PRINT1("Error %d on string removal", r); + } + r = iPort[portNumber].RemoveStringDescriptor(stridx2); + if (r != KErrNone) + { + TUSB_PRINT1("Error %d on string removal", r); + } + } + TUSB_VERBOSE_PRINT1 ("Closing USB channel number %d",portNumber); + iPort[portNumber].Close(); // close USB channel + } + TUSB_VERBOSE_PRINT("Closing Idle Counter Thread"); + iIdleCounter->iCommand = ETestIdleCounterClose; + iIdleCounterChunk.Close(); + // Allow time for low-priority thread to close + User::After(100000); + iIdleCounterThread.Close(); + + CActiveScheduler::Stop(); + break; + + case EVersion : + TUSB_PRINT("Receiving t_usb_host version"); + host_ver_major = iEp0DataBuffer[0]; + host_ver_minor = iEp0DataBuffer[1]; + host_ver_micro = iEp0DataBuffer[2]; + usbio_ver_major = iEp0DataBuffer[3]; + usbio_ver_minor = iEp0DataBuffer[4]; + TUSB_PRINT5("Host-side: t_usb_host v%d.%d.%d USBIO v%d.%d\n", + host_ver_major, host_ver_minor, host_ver_micro, + usbio_ver_major, usbio_ver_minor); + if (host_ver_major < KHostVersionMajor) + { + TUSB_PRINT1("t_usb_host version not sufficient (need at least v%d.x.x)\n",KHostVersionMajor); + User::Leave(-1); + return KErrNone; + } + // Just using '<' instead of the seemingly absurd '<= && !==' doesn't work without + // GCC compiler warning because Kxxx can also be zero (in which case there's no '<'). + else if ((host_ver_minor <= KHostVersionMinor) && + !(host_ver_minor == KHostVersionMinor)) + { + TUSB_PRINT2("t_usb_host version not sufficient (need at least v%d.%d.x)\n", + KHostVersionMajor, KHostVersionMinor); + test(EFalse); + return KErrNone; + } + // Just using '<' instead of the seemingly absurd '<= && !==' doesn't work without + // GCC compiler warning because Kxxx can also be zero (in which case there's no '<'). + else if ((host_ver_micro <= KHostVersionMicro) && + !(host_ver_micro == KHostVersionMicro)) + { + TUSB_PRINT3("USBRFLCT version not sufficient (need at least v%d.%d.%d)\n", + KHostVersionMajor, KHostVersionMinor, KHostVersionMicro); + test(EFalse); + return KErrNone; + } + break; + + case ETestParam : + tpPtr = (TestParamPtr)(&iEp0DataBuffer[0]); + TUSB_VERBOSE_PRINT4("Test Params - interface %d repeat %d settingRepeat %d beforeIndex %d",tpPtr->interfaceNumber,tpPtr->repeat,tpPtr->settingRepeat,tpPtr->beforeIndex); + if (index >= KMaxConcurrentTests) + { + TUSB_PRINT2("Test index %d is greater than maximum allowed (%d) concurrent tests",index,KMaxConcurrentTests); + test(EFalse); + return KErrNone; + } + // Create Reader/Writer active object + pActiveRW = CActiveRW::NewL(iConsole, &iPort[gInterfaceConfig[tpPtr->interfaceNumber][tpPtr->alternateSetting]->iPortNumber], iFs, index, lastSettingThread); + if (!pActiveRW) + { + TUSB_PRINT("Failed to create reader/writer"); + test(EFalse); + return KErrNone; + } + TUSB_VERBOSE_PRINT("Created reader/writer"); + pActiveRW->SetTestParams(tpPtr); + switch (value) + { + case 'X' : + test.Start (_L("Xml")); + break; + + case 'L' : + test.Start (_L("Loop")); + pActiveRW->SetTransferMode(ELoop); + gAltSettingOnNotify = ETrue; + if (tpPtr->settingRepeat && !firstSettingThread) + { + pActiveRW->Suspend(ESuspend); + } + else + { + pActiveRW->StartOrSuspend(); + } + break; + + case 'C' : + test.Start (_L("Compare")); + pActiveRW->SetTransferMode(ELoopComp); + gAltSettingOnNotify = ETrue; + if (tpPtr->settingRepeat && !firstSettingThread) + { + pActiveRW->Suspend(ESuspend); + } + else + { + pActiveRW->StartOrSuspend(); + } + break; + + case 'S' : + test.Start (_L("Stream")); + if (tpPtr->outPipe > KMaxEndpointsPerClient) + { + pActiveRW->SetTransferMode(ETransmitOnly); + gAltSettingOnNotify = ETrue; + if (tpPtr->settingRepeat && !firstSettingThread) + { + pActiveRW->Suspend(ESuspend); + } + else + { + pActiveRW->StartOrSuspend(); + } + } + else + { + pActiveRW->SetTransferMode(EReceiveOnly); + gAltSettingOnNotify = ETrue; + if (tpPtr->settingRepeat && !firstSettingThread) + { + pActiveRW->Suspend(ESuspend); + } + else + { + pActiveRW->StartOrSuspend(); + } + } + break; + + case 'F' : + test.Start (_L("File")); + // send this now as the file setup takes a long time + sendStatus = EFalse; + r = iPort[0].SendEp0StatusPacket(); + test_KErrNone(r); + if (tpPtr->outPipe > KMaxEndpointsPerClient) + { + pActiveRW->SetTransferMode(ETransmitOnly); + TInt maxFileSize = tpPtr->maxSize * tpPtr->repeat; + pActiveRW->ReadFromDisk((TChar)tpPtr->minSize,maxFileSize); + gAltSettingOnNotify = ETrue; + if (tpPtr->settingRepeat && !firstSettingThread) + { + pActiveRW->Suspend(ESuspend); + } + else + { + pActiveRW->StartOrSuspend(); + } + } + else + { + pActiveRW->SetTransferMode(EReceiveOnly); + pActiveRW->WriteToDisk((TChar)tpPtr->minSize); + gAltSettingOnNotify = ETrue; + if (tpPtr->settingRepeat && !firstSettingThread) + { + pActiveRW->Suspend(ESuspend); + } + else + { + pActiveRW->StartOrSuspend(); + } + } + break; + + default : + TUSB_PRINT1("Invalid test value %X",value); + test(EFalse); + } + + gRW[index] = pActiveRW; + break; + + case ETestResult : + TUSB_VERBOSE_PRINT2 ("Test index %d complete - value %d",index,value); + // if failure, send this first to prevent panic corrupting EP0 + if (!value) + { + sendStatus = EFalse; + r = iPort[0].SendEp0StatusPacket(); + } + if (index < KMaxConcurrentTests) + { + if (gRW[index] != NULL) + { + gRW[index]->TestComplete (value); + break; + } + } + if (index == KHostErrorIndex) + { + if (!value) + { + TUSB_PRINT("Host Test Fail"); + } + } + else + { + TUSB_PRINT2("Invalid test index %d for result %d",index,value); + } + if (!value) + { + test(EFalse); + } + break; + + case ETestFail : + User::Leave(-1); + break; + + case ETestConnect : + test.Start (_L("Connect")); + sendStatus = EFalse; + r = iPort[0].SendEp0StatusPacket(); + if (iSoftwareConnect) + { + r = iPort[0].DeviceDisconnectFromHost(); + test_KErrNone (r); + + TUint32 waitTime = (TUint32)value * 1000; + if (waitTime == 0) + { + waitTime = 5000; // default to 5 milliseconds + } + iTimer.After(iStatus,waitTime); + iPending = EPendingTimer; + + SetActive(); + } + else + { + iConsole->Printf(_L("This device does not support software\n")); + iConsole->Printf(_L("disconnect/reconnect\n")); + iConsole->Printf(_L("Please physically unplug and replug\n")); + iConsole->Printf(_L("the USB cable NOW... ")); + test.End (); + } + break; + + case ETestDisconnect : + test.Start (_L("Disconnect")); + // send this now as the port will be disconnected + sendStatus = EFalse; + r = iPort[0].SendEp0StatusPacket(); + if (iSoftwareConnect) + { + r = iPort[0].DeviceDisconnectFromHost(); + test_KErrNone (r); + } + else + { + iConsole->Printf(_L("This device does not support software\n")); + iConsole->Printf(_L("disconnect/reconnect\n")); + iConsole->Printf(_L("Please physically unplug and replug\n")); + iConsole->Printf(_L("the USB cable NOW... ")); + } + + test.End (); + break; + + case ETestMassStorage : + test.Start (_L("Select Mass Storage")); + + // send this now as the port will be disconnected + sendStatus = EFalse; + r = iPort[0].SendEp0StatusPacket(); + test_KErrNone(r); + + for (TInt portNumber = 0; portNumber < iTotalChannels; portNumber++) + { + delete iDeviceStateNotifier[portNumber]; + delete iStallNotifier[portNumber]; + if (portNumber == 0) + { + r = iPort[portNumber].RemoveStringDescriptor(stridx1); + if (r != KErrNone) + { + TUSB_PRINT1("Error %d on string removal", r); + } + r = iPort[portNumber].RemoveStringDescriptor(stridx2); + if (r != KErrNone) + { + TUSB_PRINT1("Error %d on string removal", r); + } + } + TUSB_VERBOSE_PRINT1 ("Closing USB channel number %d",portNumber); + iPort[portNumber].Close(); // close USB channel + } + + r = iPort[0].Open(0); + test_KErrNone(r); + TUSB_VERBOSE_PRINT("Successfully opened USB port"); + + SetupDescriptors(iLddPtr, &iPort[0],value); + StartMassStorage(&iPort[0]); + + test.Next (_L("Enumeration...")); + r = ReEnumerate(); + test_KErrNone(r); + + + test.End (); + break; + } + if (sendStatus) + { + r = iPort[0].SendEp0StatusPacket(); + if (r != KErrNone) + { + TUSB_PRINT1("ActiveControl::Error %d in Ep0 Send Status Packet", r); + test(EFalse); + return KErrNone; + } + } + } + else + { + if ((iEp0SetUpPacket[KUsb_Ep0RequestOffset] == EVersion) && length > 0) + { + TUSB_PRINT4("Sending t_usb_device version: %d.%d.%d length %d \n", KDeviceVersionMajor, KDeviceVersionMinor, KDeviceVersionMicro, length); + #ifdef USB_SC + TUint8 *ep0Buffer; + TUint8 *ep0BufPtr; + TUint ep0Length; + iEp0Buf.GetInBufferRange(((TAny*&)ep0Buffer),ep0Length); + + ep0BufPtr = ep0Buffer; + *(ep0Buffer++) = KDeviceVersionMajor; + *(ep0Buffer++) = KDeviceVersionMinor; + *(ep0Buffer++) = KDeviceVersionMicro; + TUint8 i=3; + if (iConfigFileName->Length()) + { + for(TUint8 j=0; j < iConfigFileName->Length() && i < length; j++) + { + i++; + *(ep0Buffer++) = (*iConfigFileName)[j]; + } + } + if (iScriptFileName->Length()) + { + for(TUint8 j=0; j < iScriptFileName->Length() && i < length; j++) + { + i++; + *(ep0Buffer++) = (*iScriptFileName)[j]; + } + } + *(ep0Buffer++) = 0; + r = iEp0Buf.WriteBuffer(ep0BufPtr,length,FALSE,ep0Status); + test_KErrNone(r); + #else + iEp0DataBuffer.FillZ(length); + iEp0DataBuffer[0] = KDeviceVersionMajor; + iEp0DataBuffer[1] = KDeviceVersionMinor; + iEp0DataBuffer[2] = KDeviceVersionMicro; + iEp0DataBuffer.SetLength(3); + iEp0DataBuffer.Append (*iConfigFileName); + iEp0DataBuffer.Append (*iScriptFileName); + iEp0DataBuffer.SetLength(length); + iPort[0].Write(ep0Status, EEndpoint0, iEp0DataBuffer, length); + #endif + User::WaitForRequest(ep0Status); + test_KErrNone(ep0Status.Int()); + } + else if ((iEp0SetUpPacket[KUsb_Ep0RequestOffset] == ETestIdleCounter) && length >= sizeof(TInt64)) + { + // for a non zero request value if any tests still active send zero otherwise the counter value + TInt64 val = (value == 0 || gActiveTestCount == 0) ? iIdleCounter->iCounter : 0; + + TUSB_PRINT1("Sending counter value %Ld\n", val); + #ifdef USB_SC + + TUint8 *ep0Buffer; + TUint ep0Length; + iEp0Buf.GetInBufferRange(((TAny*&)ep0Buffer),ep0Length); + + *((TInt64*) ep0Buffer) = val; + + r = iEp0Buf.WriteBuffer(ep0Buffer,length,FALSE,ep0Status); + test_KErrNone(r); + #else + + iEp0DataBuffer.FillZ(length); + *((TInt64*) iEp0DataBuffer.Ptr()) = val; + iEp0DataBuffer.SetLength(sizeof(TInt64)); + iPort[0].Write(ep0Status, EEndpoint0, iEp0DataBuffer, length); + #endif + + User::WaitForRequest(ep0Status); + test_KErrNone(ep0Status.Int()); + } + } + if (iEp0SetUpPacket[KUsb_Ep0RequestOffset] != EStop && iEp0SetUpPacket[KUsb_Ep0RequestOffset] != ETestConnect && + iEp0SetUpPacket[KUsb_Ep0RequestOffset] != ETestMassStorage) + { + return KErrCompletion; + } + } + else + { + TUSB_PRINT1("Error : Incorrect SetUp Packet Request Type %X", iEp0SetUpPacket[0]); + test(EFalse); + return KErrNone; + } + + return KErrNone; + } + +void CActiveControl::PrintHostLog() + { + TRequestStatus status = 0; + wchar_t lineBuf[128]; + TUint j = 0; + + TUSB_VERBOSE_PRINT("Reading Host log file\n"); + + #ifdef USB_SC + TInt r = 0; + TEndpointBuffer scReadBuf; + TAny * scReadData; + TUint8 * scCharPtr; + TUint readSize; + TBool readZlp = EFalse; + + r = iPort->OpenEndpoint(scReadBuf,firstBulkOutEndpoint); + test_KErrNone(r); + do + { + r = scReadBuf.GetBuffer (scReadData,readSize,readZlp,status); + // The following line can be reinstated once the shared chunk failure is fixed + // that prevents the readZlp flag from being set + // test_Value(r, (r == KErrNone) || (r == KErrCompletion) || (r == KErrEof)); + if (r == KErrCompletion) + { + TUSB_VERBOSE_PRINT1("Host log file %d bytes read\n",readSize); + scCharPtr = (TUint8 *)scReadData; + // Print the host log file + for (TUint i = 0; i < readSize; i++) + { + if (* scCharPtr == '\r') + { + lineBuf[j++] = '\0'; + RDebug::Print (_L("%s"),lineBuf); + j = 0; + } + else + { + if (* scCharPtr != '\n') + { + lineBuf[j++] = * scCharPtr; + } + } + scCharPtr++; + } + } + if (r == KErrNone) + { + User::WaitForRequest(status); + test_KErrNone(status.Int()); + } + } + while (r >= KErrNone && !readZlp); + #else + TPtr8 readBuf((TUint8 *)User::Alloc(KHostLogFileSize),KHostLogFileSize,KHostLogFileSize); + iPort[0].ReadUntilShort(status, (TEndpointNumber)firstBulkOutEndpoint, readBuf); + User::WaitForRequest(status); + test_KErrNone(status.Int()); + TUSB_VERBOSE_PRINT1("Host log file %d bytes read\n",readBuf.Length()); + for (TUint i = 0; i < readBuf.Length(); i++) + { + if (readBuf[i] == '\r') + { + lineBuf[j++] = '\0'; + RDebug::Print (_L("%s"),lineBuf); + j = 0; + } + else + { + if (readBuf[i] != '\n') + { + lineBuf[j++] = readBuf[i]; + } + } + } + User::Free ((TAny *)readBuf.Ptr()); + #endif + } + +void CActiveControl::QueryUsbClientL(LDDConfigPtr aLddPtr, RDEVCLIENT* aPort) + { + // Get device/endpoint capabilities + // + // A TPckg, or TPckBuf was not used in the following, because + // + // TPckgBuf databuf; + // + // doesn't work. Also, + // + // TUsbcEndpointData data[KUsbcMaxEndpoints]; + // TPckgBuf databuf(data); + // + // doesn't work. Also, + // + // TUsbcEndpointData data[KUsbcMaxEndpoints]; + // TPckgBuf databuf(data); + // + // doesn't work. + // So we seem to have to stick to the ugly cast below. + // + // TUsbcEndpointData data[KUsbcMaxEndpoints]; + // TPtr8 databuf(reinterpret_cast(data), sizeof(data), sizeof(data)); + // + + // Device + // === Device Descriptor + + test.Start(_L("Query device and Endpoint Capabilities")); + + + TUsbDeviceCaps d_caps; + TInt r = aPort->DeviceCaps(d_caps); + test_KErrNone(r); + + const TInt n = d_caps().iTotalEndpoints; + + TUSB_PRINT("### USB device capabilities:"); + TUSB_PRINT1("Number of endpoints: %d", n); + TUSB_PRINT1("Supports Software-Connect: %s", + d_caps().iConnect ? _S("yes") : _S("no")); + TUSB_PRINT1("Device is Self-Powered: %s", + d_caps().iSelfPowered ? _S("yes") : _S("no")); + TUSB_PRINT1("Supports Remote-Wakeup: %s", + d_caps().iRemoteWakeup ? _S("yes") : _S("no")); + TUSB_PRINT1("Supports High-speed: %s", + d_caps().iHighSpeed ? _S("yes") : _S("no")); + TUSB_PRINT1("Supports unpowered cable detection: %s\n", + (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower) ? + _S("yes") : _S("no")); + TUSB_PRINT(""); + + iSoftwareConnect = d_caps().iConnect; // we need to remember this + test_Equal(aLddPtr->iSoftConnect,iSoftwareConnect); + + // only check capabilities if set; therefore allowing them to be disabled + if (aLddPtr->iSelfPower) + { + test(d_caps().iSelfPowered); + } + + // only check capabilities if set; therefore allowing them to be disabled + if (aLddPtr->iRemoteWakeup) + { + test(d_caps().iRemoteWakeup); + } + + test_Equal(d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower,aLddPtr->iFeatures); + + // only check capability if set; therefore allowing it to be disabled + if (aLddPtr->iHighSpeed) + { + test(d_caps().iHighSpeed); + } + + test_Equal(aLddPtr->iNumEndpoints,n); + + // Endpoints + TUsbcEndpointData data[KUsbcMaxEndpoints]; + TPtr8 dataptr(reinterpret_cast(data), sizeof(data), sizeof(data)); + r = aPort->EndpointCaps(dataptr); + test_KErrNone(r); + + TUSB_PRINT("### USB device endpoint capabilities:"); + for (TInt i = 0; i < n; i++) + { + const TUsbcEndpointCaps* caps = &data[i].iCaps; + + + TBuf<40> sizeStr(_S("unknown")); + if (caps->iSizes == KUsbEpNotAvailable) + { + sizeStr = _S("Not Available"); + } + else + { + sizeStr.SetLength(0); + if (caps->iSizes & KUsbEpSizeCont) + sizeStr.Append(_S(" Continuous"),11); + if (caps->iSizes & KUsbEpSize8) + sizeStr.Append(_S(" 8"),2); + if (caps->iSizes & KUsbEpSize16) + sizeStr.Append(_S(" 16"),3); + if (caps->iSizes & KUsbEpSize32) + sizeStr.Append(_S(" 32"),3); + if (caps->iSizes & KUsbEpSize64) + sizeStr.Append(_S(" 64"),3); + if (caps->iSizes & KUsbEpSize128) + sizeStr.Append(_S(" 128"),4); + if (caps->iSizes & KUsbEpSize256) + sizeStr.Append(_S(" 256"),4); + if (caps->iSizes & KUsbEpSize512) + sizeStr.Append(_S(" 512"),4); + if (caps->iSizes & KUsbEpSize1023) + sizeStr.Append(_S(" 1023"),5); + if (caps->iSizes & KUsbEpSize1024) + sizeStr.Append(_S(" 1024"),5); + } + + TBuf<40> typeStr(_S("unknown")); + if (caps->iTypesAndDir == KUsbEpNotAvailable) + typeStr = _S("Not Available"); + if (caps->iTypesAndDir & (KUsbEpTypeControl | KUsbEpTypeBulk | KUsbEpTypeInterrupt | KUsbEpTypeIsochronous)) + { + typeStr.SetLength(0); + if (caps->iTypesAndDir & KUsbEpTypeBulk) + typeStr.Append(_S("Control "),8); + if (caps->iTypesAndDir & KUsbEpTypeBulk) + typeStr.Append(_S("Bulk "),5); + if (caps->iTypesAndDir & KUsbEpTypeInterrupt) + typeStr.Append(_S("Interrupt "),10); + if (caps->iTypesAndDir & KUsbEpTypeIsochronous) + typeStr.Append(_S("Isochronous"),11); + } + + TBuf<20> directionStr(_S("unknown")); + + if (caps->iTypesAndDir & KUsbEpDirIn) + directionStr = _S("In"); + if (caps->iTypesAndDir & KUsbEpDirOut) + directionStr = _S("Out"); + if (caps->iTypesAndDir & KUsbEpDirBidirect) + directionStr = _S("Both"); + + TUSB_PRINT4("Endpoint:%d Sizes =%s Type = %s - %s", + i+1,sizeStr.PtrZ(), typeStr.PtrZ(), directionStr.PtrZ()); + } + TUSB_PRINT(""); + + test.End(); + + } + + +void CActiveControl::AllocateEndpointDMA(RDEVCLIENT* aPort,TENDPOINTNUMBER aEndpoint) + { + TBool res = EFalse; + + TInt r = aPort->AllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDMA); + if (r == KErrNone) + RDebug::Print(_L("DMA allocation on endpoint %d: KErrNone"), aEndpoint); + else if (r == KErrInUse) + RDebug::Print(_L("DMA allocation on endpoint %d: KErrInUse"), aEndpoint); + else if (r == KErrNotSupported) + RDebug::Print(_L("DMA allocation on endpoint %d: KErrNotSupported"), aEndpoint); + else + RDebug::Print(_L("DMA allocation on endpoint %d: unexpected return value %d"), + aEndpoint, r); + #ifdef USB_SC + res = aPort->QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDMA); + #else + res = aPort->QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDMA); + #endif + + TUSB_PRINT2("DMA on endpoint %d %s\n", + aEndpoint, res ? _S("allocated") : _S("not allocated")); + + if ((r == KErrNone) && !res) + RDebug::Print(_L("(Allocation success but negative query result: contradiction!)\n")); + else if ((r != KErrNone) && res) + RDebug::Print(_L("(Allocation failure but positive query result: contradiction!)\n")); + } + + +void CActiveControl::DeAllocateEndpointDMA(RDEVCLIENT* aPort,TENDPOINTNUMBER aEndpoint) + { + TBool res = FALSE; + TInt r = aPort->DeAllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDMA); + if (r == KErrNone) + RDebug::Print(_L("DMA deallocation on endpoint %d: KErrNone"), aEndpoint); + else if (r == KErrNotSupported) + RDebug::Print(_L("DMA deallocation on endpoint %d: KErrNotSupported"), aEndpoint); + else + RDebug::Print(_L("DMA deallocation on endpoint %d: unexpected return value %d"), + aEndpoint, r); + #ifdef USB_SC + res = aPort->QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDMA); + #else + res = aPort->QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDMA); + #endif + + TUSB_PRINT2("DMA on endpoint %d %s\n", + aEndpoint, res ? _S("allocated") : _S("not allocated")); + } + +#ifndef USB_SC +void CActiveControl::AllocateDoubleBuffering(RDEVCLIENT* aPort,TENDPOINTNUMBER aEndpoint) + { + TBool res = FALSE; + TInt r = aPort->AllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDoubleBuffering); + if (r == KErrNone) + RDebug::Print(_L("Double Buffering allocation on endpoint %d: KErrNone"), aEndpoint); + else if (r == KErrInUse) + RDebug::Print(_L("Double Buffering allocation on endpoint %d: KErrInUse"), aEndpoint); + else if (r == KErrNotSupported) + RDebug::Print(_L("Double Buffering allocation on endpoint %d: KErrNotSupported"), aEndpoint); + else + RDebug::Print(_L("Double Buffering allocation on endpoint %d: unexpected return value %d"), + aEndpoint, r); + res = aPort->QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDoubleBuffering); + TUSB_PRINT2("Double Buffering on endpoint %d %s\n", + aEndpoint, res ? _S("allocated") : _S("not allocated")); + + if ((r == KErrNone) && !res) + RDebug::Print(_L("(Allocation success but negative query result: contradiction!)\n")); + else if ((r != KErrNone) && res) + RDebug::Print(_L("(Allocation failure but positive query result: contradiction!)\n")); + } + + +void CActiveControl::DeAllocateDoubleBuffering(RDEVCLIENT* aPort,TENDPOINTNUMBER aEndpoint) + { + TInt r = aPort->DeAllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDoubleBuffering); + if (r == KErrNone) + RDebug::Print(_L("Double Buffering deallocation on endpoint %d: KErrNone"), aEndpoint); + else if (r == KErrNotSupported) + RDebug::Print(_L("Double Buffering deallocation on endpoint %d: KErrNotSupported"), aEndpoint); + else + RDebug::Print(_L("Double Buffering deallocation on endpoint %d: unexpected return value %d"), + aEndpoint, r); + TBool res = aPort->QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDoubleBuffering); + TUSB_PRINT2("Double Buffering on endpoint %d %s\n", + aEndpoint, res ? _S("allocated") : _S("not allocated")); + } + +#endif + +TInt CActiveControl::ReEnumerate() + { + TRequestStatus enum_status; + iPort[0].ReEnumerate(enum_status); + if (!iSoftwareConnect) + { + iConsole->Printf(_L("This device does not support software\n")); + iConsole->Printf(_L("disconnect/reconnect\n")); + iConsole->Printf(_L("Please physically unplug and replug\n")); + iConsole->Printf(_L("the USB cable NOW... ")); + } + iConsole->Printf(_L("\n>>> Start the t_usb_win program on the host <<<\n")); + User::WaitForRequest(enum_status); + if (enum_status != KErrNone) + { + TUSB_PRINT1("Error: Re-enumeration status = %d", enum_status.Int()); + return KErrGeneral; + } + TUsbcDeviceState device_state = EUsbcDeviceStateUndefined; + TInt r = iPort[0].DeviceStatus(device_state); + if (r != KErrNone) + { + TUSB_PRINT1("Error %d on querying device state", r); + } + else + { + TUSB_PRINT1("Current device state: %s", + (device_state == EUsbcDeviceStateUndefined) ? _S("Undefined") : + ((device_state == EUsbcDeviceStateAttached) ? _S("Attached") : + ((device_state == EUsbcDeviceStatePowered) ? _S("Powered") : + ((device_state == EUsbcDeviceStateDefault) ? _S("Default") : + ((device_state == EUsbcDeviceStateAddress) ? _S("Address") : + ((device_state == EUsbcDeviceStateConfigured) ? _S("Configured") : + ((device_state == EUsbcDeviceStateSuspended) ? _S("Suspended") : + _S("Unknown")))))))); + } + + // Check the speed of the established physical USB connection + iHighSpeed = iPort[0].CurrentlyUsingHighSpeed(); + if (iHighSpeed) + { + TUSB_PRINT("---> USB High-speed Testing\n"); + } + else + { + TUSB_PRINT("---> USB Full-speed Testing\n"); + } + + return KErrNone; + } + +// -eof-