Update contrib.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // @file testdevicebase.cpp
19 #include "TestDeviceBase.h"
20 #include "UsbDescriptorOffsets.h"
21 #include "testdebug.h"
23 #include "softwareconnecttimer.h"
24 #include "wakeuptimer.h"
25 #include "controltransferrequests.h"
26 #include "testinterfacebase.h"
27 #include "PBASE-T_USBDI-0486.h"
28 #include <e32property.h>
30 namespace NUnitTesting_USBDI
33 RUsbTestDevice::RUsbTestDevice()
34 : iStateWatcher(NULL),
35 iCurrentState(EUsbcDeviceStateUndefined),
37 iConnectTimer(NULL), iWakeupTimer(NULL),
42 RUsbTestDevice::RUsbTestDevice(CBaseTestCase* aTestCase)
43 : iStateWatcher(NULL),
44 iCurrentState(EUsbcDeviceStateUndefined),
46 iConnectTimer(NULL), iWakeupTimer(NULL),
50 iTestCase = aTestCase;
51 RDebug::Printf("iTestCase = %d", iTestCase);
54 void RUsbTestDevice::ResetState()
56 iCurrentState = EUsbcDeviceStateUndefined;
59 RUsbTestDevice::~RUsbTestDevice()
65 void RUsbTestDevice::Close()
74 iInterfaces.ResetAndDestroy();
76 iClientDriver.Close();
78 if(!iTestCase->IsHost()) // process only started in client rom
80 // create a publish/subscribe key to allow usbhost_usbman to be killed
82 static const TUid KWordOfDeathCat = {0x01066600};
83 static const TInt KWordOfDeathKey = 0x01066601;
84 static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
85 TInt r = RProperty::Define(KWordOfDeathCat, KWordOfDeathKey, RProperty::EInt,KAllowAllPolicy, KAllowAllPolicy, 0);
88 RDebug::Print(_L("Could not create the WordOfDeath P&S (%d)"), r);
90 RDebug::Printf("killing t_usbhost_usbman.exe");
91 RProperty::Set(KWordOfDeathCat, KWordOfDeathKey, KErrAbort); // Send the word of death
92 User::After(1000000); //allow time for t_usbhost_usbman.exe to clean up
97 void RUsbTestDevice::SubscribeToReports(TRequestStatus& aObserverStatus)
101 // Signal the request as pending
103 iObserverStatus = &aObserverStatus;
104 *iObserverStatus = KRequestPending;
108 void RUsbTestDevice::CancelSubscriptionToReports()
112 // Signal the request as cancelled
113 User::RequestComplete(iObserverStatus,KErrCancel);
117 void RUsbTestDevice::OpenL()
122 RDebug::Printf("starting t_usbhost_usbman.exe");
123 TInt r = iOtgUsbMan.Create(_L("t_usbhost_usbman.exe"), _L("client"));
124 gtest(r == KErrNone);
127 User::After(1500000);
129 // Open channel to driver
130 err = iClientDriver.Open(0);
133 RDebug::Printf("<Error %d> Unable to open a channel to USB client driver",err);
137 // Hide bus from host while interfaces are being set up
138 err = iClientDriver.DeviceDisconnectFromHost();
141 RDebug::Printf("<Error %d> unable to disconnect device from host",err);
145 // Create the client usb state watcher
146 iStateWatcher = CUsbClientStateWatcher::NewL(iClientDriver,*this);
148 // Create the Ep0 reader
149 iDeviceEp0 = CDeviceEndpoint0::NewL(*this);
151 // Create the timer for software connection/disconnection
152 iConnectTimer = CSoftwareConnectTimer::NewL(*this);
154 // Create the timer for remote wakeup events
155 iWakeupTimer = CRemoteWakeupTimer::NewL(*this);
158 User::LeaveIfError(iClientDriver.DeviceCaps(iDeviceCaps));
159 RDebug::Printf("------ USB device capabilities -------");
160 RDebug::Printf("Number of endpoints: %d",iDeviceCaps().iTotalEndpoints);
161 RDebug::Printf("Supports Software-Connect: %S",iDeviceCaps().iConnect ? &KYes() : &KNo());
162 RDebug::Printf("Device is Self-Powered: %S",iDeviceCaps().iSelfPowered ? &KYes() : &KNo());
163 RDebug::Printf("Supports Remote-Wakeup: %S",iDeviceCaps().iRemoteWakeup ? &KYes() : &KNo());
164 RDebug::Printf("Supports High-speed: %S",iDeviceCaps().iHighSpeed ? &KYes() : &KNo());
165 RDebug::Printf("Supports unpowered cable detection: %S",(iDeviceCaps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower) ? &KYes() : &KNo());
166 RDebug::Printf("--------------------------------------");
171 TInt RUsbTestDevice::SetClassCode(TUint8 aClassCode,TUint8 aSubClassCode,TUint8 aDeviceProtocol)
175 // Get Device descriptor
176 TBuf8<KUsbDescSize_Device> deviceDescriptor;
177 TInt err(iClientDriver.GetDeviceDescriptor(deviceDescriptor));
180 RDebug::Printf("<Error %d> Unable to obtain device descriptor",err);
184 deviceDescriptor[KDevDescOffset_bDeviceClass] = aClassCode;
185 deviceDescriptor[KDevDescOffset_bDeviceSubClass] = aSubClassCode;
186 deviceDescriptor[KDevDescOffset_bDeviceProtocol] = aDeviceProtocol;
188 err = iClientDriver.SetDeviceDescriptor(deviceDescriptor);
191 RDebug::Printf("<Error %d> Unable to set the device dsecriptor",err);
198 TInt RUsbTestDevice::SetUsbSpecification(TUint16 aSpecification)
202 // Get Device descriptor
203 TBuf8<KUsbDescSize_Device> deviceDescriptor;
204 TInt err(iClientDriver.GetDeviceDescriptor(deviceDescriptor));
207 RDebug::Printf("<Error %d> Unable to obtain device descriptor",err);
212 TUint8* p = reinterpret_cast<TUint8*>(&aSpecification);
213 deviceDescriptor[KDevDescOffset_bcdUSB] = *p;
214 deviceDescriptor[KDevDescOffset_bcdUSB+1] = *(p+1);
216 // Symbian currently supports only devices with one configuration by selecting the configurations
217 // that has the lowest power consumption
219 deviceDescriptor[KDevDescOffset_bNumConfigurations] = 0x01;
221 err = iClientDriver.SetDeviceDescriptor(deviceDescriptor);
224 RDebug::Printf("<Error %d> Unable to set the device dsecriptor",err);
231 TInt RUsbTestDevice::SetVendor(TUint16 aVendorId)
235 // Get Device descriptor
236 TBuf8<KUsbDescSize_Device> deviceDescriptor;
237 TInt err(iClientDriver.GetDeviceDescriptor(deviceDescriptor));
240 RDebug::Printf("<Error %d> Unable to obtain device descriptor",err);
245 TUint8* p = reinterpret_cast<TUint8*>(&aVendorId);
246 deviceDescriptor[KDevDescOffset_idVendor] = *p;
247 deviceDescriptor[KDevDescOffset_idVendor+1] = *(p+1);
249 err = iClientDriver.SetDeviceDescriptor(deviceDescriptor);
252 RDebug::Printf("<Error %d> Unable to set the device descriptor",err);
259 TInt RUsbTestDevice::SetProduct(TUint16 aProductId,const TDesC16& aProductString,
260 const TDesC16& aManufacturerString,const TDesC16& aSerialNumberString)
264 // Get Device descriptor
265 TBuf8<KUsbDescSize_Device> deviceDescriptor;
266 TInt err(iClientDriver.GetDeviceDescriptor(deviceDescriptor));
269 RDebug::Printf("<Error %d> Unable to obtain device descriptor",err);
274 TUint8* p = reinterpret_cast<TUint8*>(&aProductId);
275 deviceDescriptor[KDevDescOffset_idProduct] = *p;
276 deviceDescriptor[KDevDescOffset_idProduct+1] = *(p+1);
278 err = iClientDriver.SetDeviceDescriptor(deviceDescriptor);
281 RDebug::Printf("<Error %d> Unable to set the device dsecriptor",err);
285 RDebug::Printf("Product Identity set");
288 err = iClientDriver.SetProductStringDescriptor(aProductString);
291 RDebug::Printf("<Error %d> Unable to set product string descriptor",err);
295 // Manufacturer string
296 err = iClientDriver.SetManufacturerStringDescriptor(aManufacturerString);
299 RDebug::Printf("<Error %d> Unable to set the manufacturer string descriptor",err);
303 // Serial number string
304 err = iClientDriver.SetSerialNumberStringDescriptor(aSerialNumberString);
307 RDebug::Printf("<Error %d> Unable to set the serial number string descriptor",err);
315 TInt RUsbTestDevice::SetConfigurationString(const TDesC16& aConfigString)
319 TInt err(iClientDriver.SetConfigurationStringDescriptor(aConfigString));
322 RDebug::Printf("<Error %d> Unable to set configuration string descriptor",err);
328 void RUsbTestDevice::AddInterface(CInterfaceBase* aInterface)
332 // Add the interface to the device
333 TInt err = iInterfaces.Append(aInterface);
337 RDebug::Printf("<Error %d> Unable to add interface",err);
338 return ReportError(err);
343 CInterfaceBase& RUsbTestDevice::Interface(TInt aIndex)
345 return *iInterfaces[aIndex];
349 void RUsbTestDevice::SoftwareConnect()
352 TInt err(iClientDriver.PowerUpUdc());
353 if((err != KErrNone) && (err != KErrNotReady))
355 RDebug::Printf("<Error %d> Power Up Udc",err);
359 if(iDeviceCaps().iConnect)
361 err = iClientDriver.DeviceConnectToHost();
364 RDebug::Printf("<Error %d> Unable to connect to the host",err);
370 RDebug::Printf("Please connect device to Host");
374 void RUsbTestDevice::SoftwareDisconnect()
378 if(iDeviceCaps().iConnect)
380 TInt err(iClientDriver.DeviceDisconnectFromHost());
383 RDebug::Printf("<Error %d> Unable to disconnect from the host",err);
389 RDebug::Printf("Please disconnect device from Host");
395 void RUsbTestDevice::RemoteWakeup()
398 if(iDeviceCaps().iConnect)
400 TInt err(iClientDriver.SignalRemoteWakeup());
403 RDebug::Printf("<Error %d> Unable to perform a remote wakeup",err);
409 RDebug::Printf("remote wakeup not supported");
414 TInt RUsbTestDevice::ProcessRequestL(TUint8 aRequest,TUint16 aValue,TUint16 aIndex,
415 TUint16 aDataReqLength,const TDesC8& aPayload)
419 if(aRequest == KVendorEmptyRequest)
421 // Handle an empty request (i.e. do nothing)
423 AcknowledgeRequestReceived();
425 else if(aRequest == KVendorReconnectRequest)
427 // Handle a reconnect requests from the host
429 AcknowledgeRequestReceived();
430 iConnectTimer->SoftwareReConnect(aValue);
432 else if(aRequest == KVendorDisconnectDeviceAThenConnectDeviceCRequest)
434 RDebug::Printf("**aRequest == KVendorDisconnectDeviceAThenConnectDeviceCRequest, this = 0x%08x", this);
435 // Handle a reconnect requests from the host
436 AcknowledgeRequestReceived();
438 SoftwareDisconnect();
439 User::After(1000000);
440 // connect device C now
441 CUT_PBASE_T_USBDI_0486* iTestCaseT_USBDI_0486 = reinterpret_cast<CUT_PBASE_T_USBDI_0486*>(iTestCase);
444 User::After(3000000);
445 iTestCaseT_USBDI_0486->TestDeviceC()->OpenL(KTestDeviceC_SN);
446 // Connect the device to the host
447 iTestCaseT_USBDI_0486->TestDeviceC()->SoftwareConnect();
450 else if(aRequest == KVendorDisconnectDeviceCThenConnectDeviceARequest)
452 RDebug::Printf("**aRequest == KVendorDisconnectDeviceCThenConnectDeviceARequest, this = 0x%08x", this);
453 // Handle a reconnect requests from the host
454 AcknowledgeRequestReceived();
456 SoftwareDisconnect();
457 User::After(1000000);
459 // connect device A now
460 CUT_PBASE_T_USBDI_0486* iTestCaseT_USBDI_0486 = reinterpret_cast<CUT_PBASE_T_USBDI_0486*>(iTestCase);
464 User::After(3000000);
465 iTestCaseT_USBDI_0486->Cancel();
466 iTestCaseT_USBDI_0486->HandleDeviceDConnection();
467 iTestCaseT_USBDI_0486->TestDeviceD()->OpenL(iTestCaseT_USBDI_0486->TestCaseId());
469 // Connect the device to the host
470 iTestCaseT_USBDI_0486->TestDeviceD()->SoftwareConnect();
473 else if(aRequest == KVendorTestCasePassed)
475 // Test case has completed successfully
476 // so report to client test case that host is happy
478 AcknowledgeRequestReceived();
479 ReportError(KErrNone);
481 else if(aRequest == KVendorTestCaseFailed)
483 // The test case has failed, so report to client test case
484 // and display/log the error message
486 AcknowledgeRequestReceived();
488 HBufC16* msg = HBufC16::NewL(aPayload.Length());
489 msg->Des().Copy(aPayload);
490 RDebug::Printf("<Host> Test case failed: %S",msg);
493 ReportError(-aValue);
495 else if(aRequest == KVendorRemoteWakeupRequest)
497 // Handle a remote wakeup request
499 AcknowledgeRequestReceived();
500 iWakeupTimer->WakeUp(aValue);
502 else if(aRequest == KVendorPutPayloadRequest)
504 // Handle a payload request from the host
506 AcknowledgeRequestReceived();
507 RDebug::Printf("Put payload");
508 if(aPayload.Compare(_L8("DEADBEEF")) != 0)
510 RDebug::Printf("<Error %d> Payload not as expected",KErrCorrupt);
511 ReportError(KErrCorrupt);
514 else if(aRequest == KVendorGetPayloadRequest)
516 // Handle a payload request to the host
518 RDebug::Printf("Get payload");
519 __ASSERT_DEBUG(iAuxBuffer, User::Panic(_L("Trying to write non-allocated buffer"), KErrGeneral));
520 RDebug::Printf("iAuxBuffer = ....");
521 RDebug::RawPrint(*iAuxBuffer);
522 RDebug::Printf("\n");
524 //Perform synchronous write to EP0
525 //This allows the subsequent 'Read' request to
527 TInt ret = iDeviceEp0->SendDataSynchronous(*iAuxBuffer);
528 RDebug::Printf("Write (from device callback) executed with error %d", ret);
530 else if(aRequest == KVendorUnrespondRequest)
532 // Do not acknowledge this request
534 RDebug::Printf("Unrespond request: continually NAK the host");
536 else if(aRequest == KVendorStallRequest)
538 // Stall the specified endpoint
540 AcknowledgeRequestReceived();
541 RDebug::Printf("Stalling endpoint %d",aValue);
546 // Maybe forward to derived classes
552 void RUsbTestDevice::StateChangeL(TUsbcDeviceState aNewState,TInt aChangeCompletionCode)
556 RDebug::Printf("Client state change to %d err=%d",aNewState,aChangeCompletionCode);
558 // Notify the test case of failed state change notification
560 if(aChangeCompletionCode != KErrNone)
562 return ReportError(aChangeCompletionCode);
565 // Check the state change
567 if(iCurrentState == EUsbcDeviceStateConfigured)
569 // Device is already in a fully configured state
571 if(aNewState == EUsbcDeviceStateConfigured)
573 // Do nothing as this is the current state anyway
577 // The is a state change from EUsbcDeviceStateConfigured to aNewState
578 // so stop reading from control ep0
580 RDebug::Printf("Ignoring control ep0");
582 // Stop reading ep0 directed requests
588 iCurrentState = aNewState;
593 // Device is not in a fully configured state
595 if(aNewState == EUsbcDeviceStateConfigured)
597 // Device has now been placed into a fully configured state by the host
598 // so start reading from control ep0
600 RDebug::Printf("Reading from control ep0");
602 // Start reading ep0 directed requests
608 iCurrentState = aNewState;
612 // Just update the state
614 iCurrentState = aNewState;
618 // Forward the state change notification to derived classes
620 OnStateChangeL(aNewState);
624 void RUsbTestDevice::StartEp0Reading()
628 // Start reading device directed ep0 requests
630 TInt err(iDeviceEp0->Start());
633 return ReportError(err);
636 // Start reading interface directed requests
638 TInt interfaceCount(iInterfaces.Count());
639 for(TInt i=0; i<interfaceCount; i++)
641 iInterfaces[i]->StartEp0Reading();
646 void RUsbTestDevice::StopEp0Reading()
650 // Stop reading interface directed requests
652 TInt interfaceCount(iInterfaces.Count());
653 for(TInt i=0; i<interfaceCount; i++)
655 iInterfaces[i]->StopEp0Reading();
658 // Stop reading device directed requests from ep0
660 TInt err(iDeviceEp0->Stop());
663 return ReportError(err);
668 void RUsbTestDevice::AcknowledgeRequestReceived()
672 TInt err(iDeviceEp0->Reader().Acknowledge());
673 RDebug::Printf("err = %d",err);
682 void RUsbTestDevice::ReportError(TInt aCompletionCode)
685 RDebug::Printf("err or aCompletionCode = %d, observer status = %d, KRequestPending = %d",
686 aCompletionCode, iObserverStatus->Int(), KRequestPending);
687 if(*iObserverStatus == KRequestPending)
689 RDebug::Printf("In complete request");
690 User::RequestComplete(iObserverStatus,aCompletionCode);