diff -r 000000000000 -r a41df078684a kerneltest/e32test/usbho/t_usbdi/src/TestDeviceBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/usbho/t_usbdi/src/TestDeviceBase.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,696 @@ +// 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: +// @file testdevicebase.cpp +// @internalComponent +// +// + +#include "TestDeviceBase.h" +#include "UsbDescriptorOffsets.h" +#include "testdebug.h" +#include +#include "softwareconnecttimer.h" +#include "wakeuptimer.h" +#include "controltransferrequests.h" +#include "testinterfacebase.h" +#include "PBASE-T_USBDI-0486.h" +#include + +namespace NUnitTesting_USBDI + { + +RUsbTestDevice::RUsbTestDevice() +: iStateWatcher(NULL), + iCurrentState(EUsbcDeviceStateUndefined), + iDeviceEp0(NULL), + iConnectTimer(NULL), iWakeupTimer(NULL), + iAuxBuffer(NULL) + { + } + +RUsbTestDevice::RUsbTestDevice(CBaseTestCase* aTestCase) +: iStateWatcher(NULL), + iCurrentState(EUsbcDeviceStateUndefined), + iDeviceEp0(NULL), + iConnectTimer(NULL), iWakeupTimer(NULL), + iAuxBuffer(NULL) + { + LOG_FUNC + iTestCase = aTestCase; + RDebug::Printf("iTestCase = %d", iTestCase); + } + +void RUsbTestDevice::ResetState() + { + iCurrentState = EUsbcDeviceStateUndefined; + } + +RUsbTestDevice::~RUsbTestDevice() + { + LOG_FUNC + + } + +void RUsbTestDevice::Close() + { + LOG_FUNC + + delete iWakeupTimer; + delete iConnectTimer; + delete iDeviceEp0; + delete iStateWatcher; + + iInterfaces.ResetAndDestroy(); + + iClientDriver.Close(); + + if(!iTestCase->IsHost()) // process only started in client rom + { + // create a publish/subscribe key to allow usbhost_usbman to be killed + // cleanly + static const TUid KWordOfDeathCat = {0x01066600}; + static const TInt KWordOfDeathKey = 0x01066601; + static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy); + TInt r = RProperty::Define(KWordOfDeathCat, KWordOfDeathKey, RProperty::EInt,KAllowAllPolicy, KAllowAllPolicy, 0); + if(r != KErrNone) + { + RDebug::Print(_L("Could not create the WordOfDeath P&S (%d)"), r); + } + RDebug::Printf("killing t_usbhost_usbman.exe"); + RProperty::Set(KWordOfDeathCat, KWordOfDeathKey, KErrAbort); // Send the word of death + User::After(1000000); //allow time for t_usbhost_usbman.exe to clean up + } + } + + +void RUsbTestDevice::SubscribeToReports(TRequestStatus& aObserverStatus) + { + LOG_FUNC + + // Signal the request as pending + + iObserverStatus = &aObserverStatus; + *iObserverStatus = KRequestPending; + } + + +void RUsbTestDevice::CancelSubscriptionToReports() + { + LOG_FUNC + + // Signal the request as cancelled + User::RequestComplete(iObserverStatus,KErrCancel); + } + + +void RUsbTestDevice::OpenL() + { + LOG_FUNC + TInt err = KErrNone; + + RDebug::Printf("starting t_usbhost_usbman.exe"); + TInt r = iOtgUsbMan.Create(_L("t_usbhost_usbman.exe"), _L("client")); + gtest(r == KErrNone); + iOtgUsbMan.Resume(); + + User::After(1500000); + + // Open channel to driver + err = iClientDriver.Open(0); + if(err != KErrNone) + { + RDebug::Printf(" Unable to open a channel to USB client driver",err); + User::Leave(err); + } + + // Hide bus from host while interfaces are being set up + err = iClientDriver.DeviceDisconnectFromHost(); + if(err != KErrNone) + { + RDebug::Printf(" unable to disconnect device from host",err); + User::Leave(err); + } + + // Create the client usb state watcher + iStateWatcher = CUsbClientStateWatcher::NewL(iClientDriver,*this); + + // Create the Ep0 reader + iDeviceEp0 = CDeviceEndpoint0::NewL(*this); + + // Create the timer for software connection/disconnection + iConnectTimer = CSoftwareConnectTimer::NewL(*this); + + // Create the timer for remote wakeup events + iWakeupTimer = CRemoteWakeupTimer::NewL(*this); + _LIT8(KYes, "yes"); + _LIT8(KNo, "no"); + User::LeaveIfError(iClientDriver.DeviceCaps(iDeviceCaps)); + RDebug::Printf("------ USB device capabilities -------"); + RDebug::Printf("Number of endpoints: %d",iDeviceCaps().iTotalEndpoints); + RDebug::Printf("Supports Software-Connect: %S",iDeviceCaps().iConnect ? &KYes() : &KNo()); + RDebug::Printf("Device is Self-Powered: %S",iDeviceCaps().iSelfPowered ? &KYes() : &KNo()); + RDebug::Printf("Supports Remote-Wakeup: %S",iDeviceCaps().iRemoteWakeup ? &KYes() : &KNo()); + RDebug::Printf("Supports High-speed: %S",iDeviceCaps().iHighSpeed ? &KYes() : &KNo()); + RDebug::Printf("Supports unpowered cable detection: %S",(iDeviceCaps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower) ? &KYes() : &KNo()); + RDebug::Printf("--------------------------------------"); + + } + + +TInt RUsbTestDevice::SetClassCode(TUint8 aClassCode,TUint8 aSubClassCode,TUint8 aDeviceProtocol) + { + LOG_FUNC + + // Get Device descriptor + TBuf8 deviceDescriptor; + TInt err(iClientDriver.GetDeviceDescriptor(deviceDescriptor)); + if(err != KErrNone) + { + RDebug::Printf(" Unable to obtain device descriptor",err); + } + else + { + deviceDescriptor[KDevDescOffset_bDeviceClass] = aClassCode; + deviceDescriptor[KDevDescOffset_bDeviceSubClass] = aSubClassCode; + deviceDescriptor[KDevDescOffset_bDeviceProtocol] = aDeviceProtocol; + + err = iClientDriver.SetDeviceDescriptor(deviceDescriptor); + if(err != KErrNone) + { + RDebug::Printf(" Unable to set the device dsecriptor",err); + } + } + return err; + } + + +TInt RUsbTestDevice::SetUsbSpecification(TUint16 aSpecification) + { + LOG_FUNC + + // Get Device descriptor + TBuf8 deviceDescriptor; + TInt err(iClientDriver.GetDeviceDescriptor(deviceDescriptor)); + if(err != KErrNone) + { + RDebug::Printf(" Unable to obtain device descriptor",err); + } + else + { + // Set bcdUSB + TUint8* p = reinterpret_cast(&aSpecification); + deviceDescriptor[KDevDescOffset_bcdUSB] = *p; + deviceDescriptor[KDevDescOffset_bcdUSB+1] = *(p+1); + + // Symbian currently supports only devices with one configuration by selecting the configurations + // that has the lowest power consumption + + deviceDescriptor[KDevDescOffset_bNumConfigurations] = 0x01; + + err = iClientDriver.SetDeviceDescriptor(deviceDescriptor); + if(err != KErrNone) + { + RDebug::Printf(" Unable to set the device dsecriptor",err); + } + } + return err; + } + + +TInt RUsbTestDevice::SetVendor(TUint16 aVendorId) + { + LOG_FUNC + + // Get Device descriptor + TBuf8 deviceDescriptor; + TInt err(iClientDriver.GetDeviceDescriptor(deviceDescriptor)); + if(err != KErrNone) + { + RDebug::Printf(" Unable to obtain device descriptor",err); + } + else + { + // Set VID + TUint8* p = reinterpret_cast(&aVendorId); + deviceDescriptor[KDevDescOffset_idVendor] = *p; + deviceDescriptor[KDevDescOffset_idVendor+1] = *(p+1); + + err = iClientDriver.SetDeviceDescriptor(deviceDescriptor); + if(err != KErrNone) + { + RDebug::Printf(" Unable to set the device descriptor",err); + } + } + return err; + } + + +TInt RUsbTestDevice::SetProduct(TUint16 aProductId,const TDesC16& aProductString, + const TDesC16& aManufacturerString,const TDesC16& aSerialNumberString) + { + LOG_FUNC + + // Get Device descriptor + TBuf8 deviceDescriptor; + TInt err(iClientDriver.GetDeviceDescriptor(deviceDescriptor)); + if(err != KErrNone) + { + RDebug::Printf(" Unable to obtain device descriptor",err); + } + else + { + // Set PID + TUint8* p = reinterpret_cast(&aProductId); + deviceDescriptor[KDevDescOffset_idProduct] = *p; + deviceDescriptor[KDevDescOffset_idProduct+1] = *(p+1); + + err = iClientDriver.SetDeviceDescriptor(deviceDescriptor); + if(err != KErrNone) + { + RDebug::Printf(" Unable to set the device dsecriptor",err); + return err; + } + + RDebug::Printf("Product Identity set"); + + // Product string + err = iClientDriver.SetProductStringDescriptor(aProductString); + if(err != KErrNone) + { + RDebug::Printf(" Unable to set product string descriptor",err); + return err; + } + + // Manufacturer string + err = iClientDriver.SetManufacturerStringDescriptor(aManufacturerString); + if(err != KErrNone) + { + RDebug::Printf(" Unable to set the manufacturer string descriptor",err); + return err; + } + + // Serial number string + err = iClientDriver.SetSerialNumberStringDescriptor(aSerialNumberString); + if(err != KErrNone) + { + RDebug::Printf(" Unable to set the serial number string descriptor",err); + return err; + } + } + return KErrNone; + } + + +TInt RUsbTestDevice::SetConfigurationString(const TDesC16& aConfigString) + { + LOG_FUNC + + TInt err(iClientDriver.SetConfigurationStringDescriptor(aConfigString)); + if(err != KErrNone) + { + RDebug::Printf(" Unable to set configuration string descriptor",err); + } + return err; + } + + +void RUsbTestDevice::AddInterface(CInterfaceBase* aInterface) + { + LOG_FUNC + + // Add the interface to the device + TInt err = iInterfaces.Append(aInterface); + + if(err != KErrNone) + { + RDebug::Printf(" Unable to add interface",err); + return ReportError(err); + } + } + + +CInterfaceBase& RUsbTestDevice::Interface(TInt aIndex) + { + return *iInterfaces[aIndex]; + } + + +void RUsbTestDevice::SoftwareConnect() + { + LOG_FUNC + TInt err(iClientDriver.PowerUpUdc()); + if((err != KErrNone) && (err != KErrNotReady)) + { + RDebug::Printf(" Power Up Udc",err); + ReportError(err); + } + + if(iDeviceCaps().iConnect) + { + err = iClientDriver.DeviceConnectToHost(); + if(err != KErrNone) + { + RDebug::Printf(" Unable to connect to the host",err); + ReportError(err); + } + } + else + { + RDebug::Printf("Please connect device to Host"); + } + } + +void RUsbTestDevice::SoftwareDisconnect() + { + LOG_FUNC + + if(iDeviceCaps().iConnect) + { + TInt err(iClientDriver.DeviceDisconnectFromHost()); + if(err != KErrNone) + { + RDebug::Printf(" Unable to disconnect from the host",err); + ReportError(err); + } + } + else + { + RDebug::Printf("Please disconnect device from Host"); + } + + } + + +void RUsbTestDevice::RemoteWakeup() + { + LOG_FUNC + if(iDeviceCaps().iConnect) + { + TInt err(iClientDriver.SignalRemoteWakeup()); + if(err != KErrNone) + { + RDebug::Printf(" Unable to perform a remote wakeup",err); + ReportError(err); + } + } + else + { + RDebug::Printf("remote wakeup not supported"); + } + } + + +TInt RUsbTestDevice::ProcessRequestL(TUint8 aRequest,TUint16 aValue,TUint16 aIndex, + TUint16 aDataReqLength,const TDesC8& aPayload) + { + LOG_FUNC + + if(aRequest == KVendorEmptyRequest) + { + // Handle an empty request (i.e. do nothing) + + AcknowledgeRequestReceived(); + } + else if(aRequest == KVendorReconnectRequest) + { + // Handle a reconnect requests from the host + + AcknowledgeRequestReceived(); + iConnectTimer->SoftwareReConnect(aValue); + } + else if(aRequest == KVendorDisconnectDeviceAThenConnectDeviceCRequest) + { + RDebug::Printf("**aRequest == KVendorDisconnectDeviceAThenConnectDeviceCRequest, this = 0x%08x", this); + // Handle a reconnect requests from the host + AcknowledgeRequestReceived(); + + SoftwareDisconnect(); + User::After(1000000); + // connect device C now + CUT_PBASE_T_USBDI_0486* iTestCaseT_USBDI_0486 = reinterpret_cast(iTestCase); + Close(); + + User::After(3000000); + iTestCaseT_USBDI_0486->TestDeviceC()->OpenL(KTestDeviceC_SN); + // Connect the device to the host + iTestCaseT_USBDI_0486->TestDeviceC()->SoftwareConnect(); + return KErrAbort; + } + else if(aRequest == KVendorDisconnectDeviceCThenConnectDeviceARequest) + { + RDebug::Printf("**aRequest == KVendorDisconnectDeviceCThenConnectDeviceARequest, this = 0x%08x", this); + // Handle a reconnect requests from the host + AcknowledgeRequestReceived(); + + SoftwareDisconnect(); + User::After(1000000); + + // connect device A now + CUT_PBASE_T_USBDI_0486* iTestCaseT_USBDI_0486 = reinterpret_cast(iTestCase); + + + Close(); + User::After(3000000); + iTestCaseT_USBDI_0486->Cancel(); + iTestCaseT_USBDI_0486->HandleDeviceDConnection(); + iTestCaseT_USBDI_0486->TestDeviceD()->OpenL(iTestCaseT_USBDI_0486->TestCaseId()); + + // Connect the device to the host + iTestCaseT_USBDI_0486->TestDeviceD()->SoftwareConnect(); + return KErrAbort; + } + else if(aRequest == KVendorTestCasePassed) + { + // Test case has completed successfully + // so report to client test case that host is happy + + AcknowledgeRequestReceived(); + ReportError(KErrNone); + } + else if(aRequest == KVendorTestCaseFailed) + { + // The test case has failed, so report to client test case + // and display/log the error message + + AcknowledgeRequestReceived(); + + HBufC16* msg = HBufC16::NewL(aPayload.Length()); + msg->Des().Copy(aPayload); + RDebug::Printf(" Test case failed: %S",msg); + delete msg; + msg = 0; + ReportError(-aValue); + } + else if(aRequest == KVendorRemoteWakeupRequest) + { + // Handle a remote wakeup request + + AcknowledgeRequestReceived(); + iWakeupTimer->WakeUp(aValue); + } + else if(aRequest == KVendorPutPayloadRequest) + { + // Handle a payload request from the host + + AcknowledgeRequestReceived(); + RDebug::Printf("Put payload"); + if(aPayload.Compare(_L8("DEADBEEF")) != 0) + { + RDebug::Printf(" Payload not as expected",KErrCorrupt); + ReportError(KErrCorrupt); + } + } + else if(aRequest == KVendorGetPayloadRequest) + { + // Handle a payload request to the host + + RDebug::Printf("Get payload"); + __ASSERT_DEBUG(iAuxBuffer, User::Panic(_L("Trying to write non-allocated buffer"), KErrGeneral)); + RDebug::Printf("iAuxBuffer = ...."); + RDebug::RawPrint(*iAuxBuffer); + RDebug::Printf("\n"); + + //Perform synchronous write to EP0 + //This allows the subsequent 'Read' request to + //take place + TInt ret = iDeviceEp0->SendDataSynchronous(*iAuxBuffer); + RDebug::Printf("Write (from device callback) executed with error %d", ret); + } + else if(aRequest == KVendorUnrespondRequest) + { + // Do not acknowledge this request + + RDebug::Printf("Unrespond request: continually NAK the host"); + } + else if(aRequest == KVendorStallRequest) + { + // Stall the specified endpoint + + AcknowledgeRequestReceived(); + RDebug::Printf("Stalling endpoint %d",aValue); + + } + else + { + // Maybe forward to derived classes + } + return KErrNone; + } + + +void RUsbTestDevice::StateChangeL(TUsbcDeviceState aNewState,TInt aChangeCompletionCode) + { + LOG_FUNC + + RDebug::Printf("Client state change to %d err=%d",aNewState,aChangeCompletionCode); + + // Notify the test case of failed state change notification + + if(aChangeCompletionCode != KErrNone) + { + return ReportError(aChangeCompletionCode); + } + + // Check the state change + + if(iCurrentState == EUsbcDeviceStateConfigured) + { + // Device is already in a fully configured state + + if(aNewState == EUsbcDeviceStateConfigured) + { + // Do nothing as this is the current state anyway + } + else + { + // The is a state change from EUsbcDeviceStateConfigured to aNewState + // so stop reading from control ep0 + + RDebug::Printf("Ignoring control ep0"); + + // Stop reading ep0 directed requests + + StopEp0Reading(); + + // Update state + + iCurrentState = aNewState; + } + } + else + { + // Device is not in a fully configured state + + if(aNewState == EUsbcDeviceStateConfigured) + { + // Device has now been placed into a fully configured state by the host + // so start reading from control ep0 + + RDebug::Printf("Reading from control ep0"); + + // Start reading ep0 directed requests + + StartEp0Reading(); + + // Update state + + iCurrentState = aNewState; + } + else + { + // Just update the state + + iCurrentState = aNewState; + } + } + + // Forward the state change notification to derived classes + + OnStateChangeL(aNewState); + } + + +void RUsbTestDevice::StartEp0Reading() + { + LOG_FUNC + + // Start reading device directed ep0 requests + + TInt err(iDeviceEp0->Start()); + if(err != KErrNone) + { + return ReportError(err); + } + + // Start reading interface directed requests + + TInt interfaceCount(iInterfaces.Count()); + for(TInt i=0; iStartEp0Reading(); + } + } + + +void RUsbTestDevice::StopEp0Reading() + { + LOG_FUNC + + // Stop reading interface directed requests + + TInt interfaceCount(iInterfaces.Count()); + for(TInt i=0; iStopEp0Reading(); + } + + // Stop reading device directed requests from ep0 + + TInt err(iDeviceEp0->Stop()); + if(err != KErrNone) + { + return ReportError(err); + } + } + + +void RUsbTestDevice::AcknowledgeRequestReceived() + { + LOG_FUNC + + TInt err(iDeviceEp0->Reader().Acknowledge()); + RDebug::Printf("err = %d",err); + if(err != KErrNone) + { + ReportError(err); + } + } + + + +void RUsbTestDevice::ReportError(TInt aCompletionCode) + { + LOG_FUNC + RDebug::Printf("err or aCompletionCode = %d, observer status = %d, KRequestPending = %d", + aCompletionCode, iObserverStatus->Int(), KRequestPending); + if(*iObserverStatus == KRequestPending) + { + RDebug::Printf("In complete request"); + User::RequestComplete(iObserverStatus,aCompletionCode); + } + } + + + } +