diff -r 000000000000 -r c9bc50fca66e usbmgmt/usbmgrtest/t_usbman/src/t_usbman.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usbmgmt/usbmgrtest/t_usbman/src/t_usbman.cpp Tue Feb 02 02:02:59 2010 +0200 @@ -0,0 +1,1164 @@ +/* +* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: +* This test program provides menu-driven functional tests for the USB Manager which exercise +* every exported API it provides. Note that, to use this program with Hurricane USB, the macro +* HURRICANE should be defined in the t_usbman.mmp file. +* WARNING: Some of these tests rely on the 'dummy class controller' build of +* USBMAN. This is produced with t_usbman_dummycc.mmp, and it includes three +* instances of the dummy class controller (mainly used for GT171 automated +* tests). To get this to operate correctly a suitable ini file must be copied +* to c:\dummy.ini, for instance usbman\data\test.ini, which provides delayed +* asynchronous Start and Stop behaviour for each of the dummy CC instances. +* +*/ + +#include +#include +#include +#include +#include +#include +#include //Publish & Subscribe header, required for setting serial number +#include "usb.h" + +LOCAL_D CConsoleBase* console; + +RTimer TheTimer; +RCommServ TheCommServ; +RUsb TheUsb; +RUsb TheSecondUsbSession; +TBool ThePrimaryClient; + +//_LIT(KUsbCsyName, "ECACM"); +//_LIT(KUsbPortName, "ACM::0"); +_LIT(KUsbLddName, "EUSBC"); + +// These are used in the startup stress test. +TInt64 TheRandomSeed = 0; +const TInt KMaxCancelTime = 2000000; +const TInt KMaxStopTime = 10000000; + +#define _printf console->Printf +#define _getch console->Getch +#define LEAVE(_x) VerboseLeaveL(_x, __LINE__, TPtrC8((const TUint8*)__FILE__), _L8(#_x)) +#define LEAVEIFERROR(_x) VerboseLeaveIfErrorL(_x, __LINE__, TPtrC8((const TUint8*)__FILE__), _L8(#_x)) +#define CHECK(_x) if (! (_x)) VerboseLeaveL(KErrGeneral, __LINE__, TPtrC8((const TUint8*)__FILE__), _L8(#_x)) + +//////////////////////////////////////////////////////////////////////////////// +// Helper functions below this point +//////////////////////////////////////////////////////////////////////////////// + +void VerboseLeaveL(TInt aError, TInt aLineNum, const TDesC8& aFileName, const TDesC8& aCode) + { + TInt filenameOffset = aFileName.LocateReverse('\\') + 1; + if (filenameOffset < 0) filenameOffset = 1; + TPtrC8 shortFileName = aFileName.Mid(filenameOffset); + TBuf<64> fName, code; + fName.Copy(shortFileName.Left(64)); + code.Copy(aCode.Left(64)); + _printf(_L("ERROR (%d) on line %d of file %S\n"), aError, aLineNum, &fName); + _printf(_L("Code: %S\n\n"), &code); + _printf(_L("[ press any key ]")); + _getch(); + User::Leave(aError); + } + +void VerboseLeaveIfErrorL(TInt aError, TInt aLineNum, const TDesC8& aFileName, const TDesC8& aCode) + { + if (aError) + VerboseLeaveL(aError, aLineNum, aFileName, aCode); + } + +void ReadString(TDes& aDes) +/** + * Reads user input into the start of the descriptor aDes. + */ + { + TChar inputKey; + TInt count = 0; + + aDes.Zero(); + for (;;) + { + inputKey = (TInt) _getch(); + + if ((TInt)inputKey == EKeyEnter) + break; + + if(inputKey == EKeyBackspace) + { + if (count > 0) + { + _printf(_L("%C"), (TUint) inputKey); + aDes.Delete(--count,1); + } + } + else if(inputKey.IsPrint()) + { + _printf(_L("%C"), (TUint) inputKey); + aDes.Append(inputKey); + count++; + } + } + } + + +void PrintUsbServiceState(TUsbServiceState aServiceState) + { + switch (aServiceState) + { + case EUsbServiceIdle: _printf(_L("USB service is idle.\n")); break; + case EUsbServiceStarting: _printf(_L("USB service is starting.\n")); break; + case EUsbServiceStarted: _printf(_L("USB service is started.\n")); break; + case EUsbServiceStopping: _printf(_L("USB service is stopping.\n")); break; +#ifndef HURRICANE + case EUsbServiceFatalError: _printf(_L("USB service has a fatal error.\n")); break; +#endif // HURRICANE + default: + _printf(_L("ERROR: unknown service state!\n")); + break; + } + } + +void PrintUsbDeviceState(TUsbDeviceState aDeviceState) + { + switch (aDeviceState) + { + case EUsbDeviceStateUndefined: + _printf(_L("USB device state is undefined.\n")); + break; + case EUsbDeviceStateDefault: + _printf(_L("USB device state is default.\n")); + break; + case EUsbDeviceStateAttached: + _printf(_L("USB device state is attached.\n")); + break; + case EUsbDeviceStatePowered: + _printf(_L("USB device state is powered.\n")); + break; + case EUsbDeviceStateConfigured: + _printf(_L("USB device state is configured.\n")); + break; + case EUsbDeviceStateAddress: + _printf(_L("USB device state is address.\n")); + break; + case EUsbDeviceStateSuspended: + _printf(_L("USB device state is suspended.\n")); + break; + default: + _printf(_L("ERROR: unknown device state!\n")); + break; + } + } + +//////////////////////////////////////////////////////////////////////////////// +// Test cases below this point +//////////////////////////////////////////////////////////////////////////////// + +void OpenUsbL() + { + LEAVEIFERROR(TheUsb.Connect()); + } + +void CloseUsbL() + { + TheUsb.Close(); + } + +// USB test cases 3.1.1, 3.1.2 and 3.1.4, startup from primary and non-primary sessions. +void StartUsbL() + { + TRequestStatus status; + TheUsb.Start(status); + User::WaitForRequest(status); + LEAVEIFERROR(status.Int()); + + _printf(_L("Started USB.\n")); + } + +// USB test cases 3.2 and (part of) 3.4, startup cancellation. +void CancelStartingUsbL(TBool aCancelByStopping) + { + TRequestStatus cancelStatus; + TRequestStatus timerStatus; + TInt cancelTime = 0; + + while (cancelTime < (100 * 1000000)) + { + _printf(_L("Cancelling after %d microseconds\n"), cancelTime); + + TheTimer.After(timerStatus, cancelTime); + TheUsb.Start(cancelStatus); + + User::WaitForRequest(cancelStatus, timerStatus); + + // If the request has finished before the timer completed, + // cancel the timer and check the request status for errors. + if (timerStatus == KRequestPending) + { + TheTimer.Cancel(); + User::WaitForRequest(timerStatus); + LEAVEIFERROR(cancelStatus.Int()); + break; + } + + // The timer should never complete with an error. + LEAVEIFERROR(timerStatus.Int()); + + // Cancel the start. The option of cancelling by stopping is only available + // from version 7.0s, because in Hurricane a stop while starting is + // actually implemented as a cancel. + +#ifndef HURRICANE + if (aCancelByStopping) + { + TRequestStatus stopStatus; + TheUsb.Stop(stopStatus); + User::WaitForRequest(stopStatus); + LEAVEIFERROR(stopStatus.Int()); + } + else +#endif // HURRICANE + { + TheUsb.StartCancel(); + } + + User::WaitForRequest(cancelStatus); + + // If the start actually completed, just return. + if (cancelStatus == KErrNone) + break; + +#ifndef HURRICANE + // If we're cancelling by stopping, then getting this error code is + // expected. + if (cancelStatus == KErrUsbServiceStopped) + { + cancelTime += 50000; + continue; + } +#endif // HURRICANE + + if (cancelStatus != KErrCancel) + LEAVE(cancelStatus.Int()); + + cancelTime += 50000; + } + + TUsbServiceState serviceState; + LEAVEIFERROR(TheUsb.GetCurrentState(serviceState)); + PrintUsbServiceState(serviceState); + } + +// Part of USB test case 3.4, stopping class controllers. +void StopUsbSynchronousL() + { + TheUsb.Stop(); + _printf(_L("Stopped USB.\n")); + } + +#ifndef HURRICANE + +// Part of USB test case 3.4, stopping class controllers. +void StopUsbAsynchronousL() + { + TRequestStatus status; + + TheUsb.Stop(status); + User::WaitForRequest(status); + LEAVEIFERROR(status.Int()); + + _printf(_L("Stopped USB.\n")); + } + +void CancelStoppingUsbL(TBool aCancelByStarting) + { + TRequestStatus cancelStatus; + TRequestStatus timerStatus; + TInt cancelTime = 0; + + while (cancelTime < (100 * 1000000)) + { + _printf(_L("Cancelling after %d microseconds\n"), cancelTime); + + TheTimer.After(timerStatus, cancelTime); + TheUsb.Stop(cancelStatus); + + User::WaitForRequest(cancelStatus, timerStatus); + + // If the request has finished before the timer completed, + // cancel the timer and check the request status for errors. + if (timerStatus == KRequestPending) + { + TheTimer.Cancel(); + User::WaitForRequest(timerStatus); + LEAVEIFERROR(cancelStatus.Int()); + break; + } + + // The timer should never complete with an error. + LEAVEIFERROR(timerStatus.Int()); + +#ifndef HURRICANE + if (aCancelByStarting) + { + TRequestStatus startStatus; + TheUsb.Start(startStatus); + User::WaitForRequest(startStatus); + LEAVEIFERROR(startStatus.Int()); + } + else +#endif // HURRICANE + { + TheUsb.StopCancel(); + } + + User::WaitForRequest(cancelStatus); + + // If the stop actually completed, just return. + if (cancelStatus == KErrNone) + break; + +#ifndef HURRICANE + // If we're cancelling by starting, then getting this + // error code is expected. + if (cancelStatus == KErrUsbServiceStarted) + { + cancelTime += 50000; + continue; + } +#endif // HURRICANE + + if (cancelStatus != KErrCancel) + LEAVE(cancelStatus.Int()); + + cancelTime += 50000; + } + + TUsbServiceState serviceState; + LEAVEIFERROR(TheUsb.GetCurrentState(serviceState)); + PrintUsbServiceState(serviceState); + } + +#endif // HURRICANE + +void RestartUsbL() + { + TheUsb.Stop(); + + TRequestStatus status; + TheUsb.Start(status); + User::WaitForRequest(status); + LEAVEIFERROR(status.Int()); + + _printf(_L("\nRestarted USB.\n")); + } + +// USB test case 3.6, stress testing of startup and shutdown. +void StartupStressTestL() + { + TRequestStatus cancelStatus; + TRequestStatus timerStatus; + TInt cancelTime = Math::Rand(TheRandomSeed) % KMaxCancelTime; + TInt stopTime; + + for (TInt i = 0; i < 100; i++) + { + _printf(_L("Cancelling after %d microseconds\n"), cancelTime); + + TheTimer.After(timerStatus, cancelTime); + TheUsb.Start(cancelStatus); + + User::WaitForRequest(cancelStatus, timerStatus); + + // If the request has finished before the timer completed, + // cancel the timer and check the request status for errors. + if (timerStatus == KRequestPending) + { + TheTimer.Cancel(); + LEAVEIFERROR(cancelStatus.Int()); + } + else + { + // The timer should never complete with an error. + LEAVEIFERROR(timerStatus.Int()); + + // Cancel the start. + TheUsb.StartCancel(); + User::WaitForRequest(cancelStatus); + } + + // If the start actually completed, then try stopping. + if (cancelStatus == KErrNone) + { + stopTime = Math::Rand(TheRandomSeed) % KMaxStopTime; + _printf(_L("Stopping after %d microseconds\n"), stopTime); + User::After(stopTime); + TheUsb.Stop(); + } + else if (cancelStatus != KErrCancel) + { + LEAVE(cancelStatus.Int()); + } + + cancelTime = Math::Rand(TheRandomSeed) % KMaxCancelTime; + } + + _printf(_L("USB is now stopped\n")); + } + +// USB test case 3.3, monitoring the state of the USB. +void MonitorUsbDeviceStateL() + { + TRequestStatus consoleStatus; + TRequestStatus notifyStatus; + TUsbServiceState serviceState; + TUsbDeviceState deviceState; + + LEAVEIFERROR(TheUsb.GetCurrentState(serviceState)); + + _printf(_L("\n")); + + PrintUsbServiceState(serviceState); + +#ifndef HURRICANE + LEAVEIFERROR(TheUsb.GetDeviceState(deviceState)); + PrintUsbDeviceState(deviceState); +#endif // HURRICANE + + _printf(_L("\nMonitoring the state of USB - press any key to stop\n\n")); + + console->Read(consoleStatus); + + while (consoleStatus == KRequestPending) + { + TheUsb.StateNotification(0xFFFFFFFF, deviceState, notifyStatus); + User::WaitForRequest(notifyStatus, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (notifyStatus != KErrNone) + { + // need to cancel the read to avoid a CBase-77 panic! + console->ReadCancel(); + LEAVE(notifyStatus.Int()); + } + } + else + { + // The user's pressed a key. + TheUsb.StateNotificationCancel(); + User::WaitForRequest(notifyStatus); + break; + } + + PrintUsbDeviceState(deviceState); + } + + _printf(_L("\nTest complete\n")); + } + +// Concurrency test case (3.9.1 in test spec). One client starts USB and then another +// one stops it. +void StartAThenStopBL() + { + LEAVEIFERROR(TheSecondUsbSession.Connect()); + + TRequestStatus status; + TUsbServiceState serviceState; + + // Start on client 1. + TheUsb.Start(status); + User::WaitForRequest(status); + LEAVEIFERROR(status.Int()); + + // Get status on both sessions. + + LEAVEIFERROR(TheUsb.GetCurrentState(serviceState)); + _printf(_L("\nSession 1: ")); + PrintUsbServiceState(serviceState); + + LEAVEIFERROR(TheSecondUsbSession.GetCurrentState(serviceState)); + _printf(_L("Session 2: ")); + PrintUsbServiceState(serviceState); + + // Stop on client 2. + TheSecondUsbSession.Stop(); + + // Get status on both sessions. + + LEAVEIFERROR(TheUsb.GetCurrentState(serviceState)); + _printf(_L("Session 1: ")); + PrintUsbServiceState(serviceState); + + LEAVEIFERROR(TheSecondUsbSession.GetCurrentState(serviceState)); + _printf(_L("Session 2: ")); + PrintUsbServiceState(serviceState); + + TheSecondUsbSession.Close(); + } + +// Concurrency test case (3.9.2 in test spec). One client stops USB while it's being +// started by another one. +void StopBWhileAStartingL() + { + LEAVEIFERROR(TheSecondUsbSession.Connect()); + + TRequestStatus status; + TUsbServiceState serviceState; + + // Start on client 1. + TheUsb.Start(status); + + // Stop on client 2. + TheSecondUsbSession.Stop(); + + // Wait for start request to complete. + User::WaitForRequest(status); + if (status.Int() != KErrUsbServiceStopped) + LEAVEIFERROR(status.Int()); + + // Get status on both sessions. + + LEAVEIFERROR(TheUsb.GetCurrentState(serviceState)); + _printf(_L("\nSession 1: ")); + PrintUsbServiceState(serviceState); + + LEAVEIFERROR(TheSecondUsbSession.GetCurrentState(serviceState)); + _printf(_L("Session 2: ")); + PrintUsbServiceState(serviceState); + + TheSecondUsbSession.Close(); + } + +// Concurrency test case (3.9.5 in test spec). One client starts USB while it's being +// started by another one. +void StartBWhileAStartingL() + { + LEAVEIFERROR(TheSecondUsbSession.Connect()); + + TRequestStatus status1; + TRequestStatus status2; + TUsbServiceState serviceState; + + // Start on client 1. + TheUsb.Start(status1); + + // Start on client 2. + TheSecondUsbSession.Start(status2); + + // Wait for first request to complete. + User::WaitForRequest(status1); + LEAVEIFERROR(status1.Int()); + + // Wait for second request to complete. + User::WaitForRequest(status2); + LEAVEIFERROR(status2.Int()); + + // Get status on both sessions. + + LEAVEIFERROR(TheUsb.GetCurrentState(serviceState)); + _printf(_L("\nSession 1: ")); + PrintUsbServiceState(serviceState); + + LEAVEIFERROR(TheSecondUsbSession.GetCurrentState(serviceState)); + _printf(_L("Session 2: ")); + PrintUsbServiceState(serviceState); + + TheSecondUsbSession.Close(); + } + +#ifndef HURRICANE + +// Concurrency test case (3.9.3 in test spec). One client starts USB while it's being +// stopped by another one. +void StartBWhileAStoppingL() + { + LEAVEIFERROR(TheSecondUsbSession.Connect()); + + TRequestStatus status1; + TRequestStatus status2; + TUsbServiceState serviceState; + + // Stop on client 1. + TheUsb.Stop(status1); + + // Start on client 2. + TheSecondUsbSession.Start(status2); + + // Wait for first request to complete. + User::WaitForRequest(status1); + if (status1.Int() != KErrUsbServiceStarted) + LEAVEIFERROR(status1.Int()); + + // Wait for second request to complete. + User::WaitForRequest(status2); + LEAVEIFERROR(status2.Int()); + + // Get status on both sessions. + + LEAVEIFERROR(TheUsb.GetCurrentState(serviceState)); + _printf(_L("\nSession 1: ")); + PrintUsbServiceState(serviceState); + + LEAVEIFERROR(TheSecondUsbSession.GetCurrentState(serviceState)); + _printf(_L("Session 2: ")); + PrintUsbServiceState(serviceState); + + TheSecondUsbSession.Close(); + } + +// Concurrency test case (3.9.4 in test spec). One client stops USB while it's being +// stopped by another one. +void StopBWhileAStoppingL() + { + LEAVEIFERROR(TheSecondUsbSession.Connect()); + + TRequestStatus status1; + TRequestStatus status2; + TUsbServiceState serviceState; + + // Stop on client 1. + TheUsb.Stop(status1); + + // Stop on client 2. + TheSecondUsbSession.Stop(status2); + + // Wait for first request to complete. + User::WaitForRequest(status1); + LEAVEIFERROR(status1.Int()); + + // Wait for second request to complete. + User::WaitForRequest(status2); + LEAVEIFERROR(status2.Int()); + + // Get status on both sessions. + + LEAVEIFERROR(TheUsb.GetCurrentState(serviceState)); + _printf(_L("\nSession 1: ")); + PrintUsbServiceState(serviceState); + + LEAVEIFERROR(TheSecondUsbSession.GetCurrentState(serviceState)); + _printf(_L("Session 2: ")); + PrintUsbServiceState(serviceState); + + TheSecondUsbSession.Close(); + } +/* +void RegisterAsPrimaryClientL() + { + LEAVEIFERROR(TheUsb.RegisterAsPrimarySession()); + ThePrimaryClient = ETrue; + } + +void DeregisterAsPrimaryClientL() + { + LEAVEIFERROR(TheUsb.DeregisterAsPrimarySession()); + ThePrimaryClient = EFalse; + } +*/ +void DbgCheckHeapL() + { + _printf(_L("Expected number of allocated heap cells: ")); + + TBuf<20> numBuf; + ReadString(numBuf); + + TLex lex(numBuf); + TInt expected; + + if (lex.Val(expected) != KErrNone) + expected = 0; + + LEAVEIFERROR(TheUsb.__DbgCheckHeap(expected)); + } + +void DbgMarkEndL() + { + _printf(_L("Expected number of allocated heap cells: ")); + + TBuf<20> numBuf; + ReadString(numBuf); + + TLex lex(numBuf); + TInt expected; + + if (lex.Val(expected) != KErrNone) + expected = 0; + + LEAVEIFERROR(TheUsb.__DbgMarkEnd(expected)); + } + +void DbgFailNextL() + { + _printf(_L("Number of allocation which will fail: ")); + + TBuf<20> numBuf; + ReadString(numBuf); + + TLex lex(numBuf); + TInt allocNumber; + + if (lex.Val(allocNumber) != KErrNone) + allocNumber = 1; + + LEAVEIFERROR(TheUsb.__DbgFailNext(allocNumber)); + } + +#endif // HURRICANE + +void SetUsbSerialNumberL() + { + //Get a number from user + TBuf16 serNum; + + _printf(_L("\nEnter new USB serial number:\n")); + ReadString(serNum); + if(serNum.Length()==0) + { + TInt r = RProperty::Delete(KUidSystemCategory,0x101FE1DB); + if(r!=KErrNotFound && r!=KErrNone) + { + User::Leave(r); + } + _printf(_L("Serial number un-published. Restart USB for change to take effect.\ne.g. Option 1 -> 1 (calls RUsb::Start)\n")); + } + else + { + _printf(_L("\nSetting serial number to %S\n"),&serNum); + //Publish the number. It will be read by CUsbDevice::SetUsbDeviceSettingsL + //The key used is the UID KUidUsbmanServer = 0x101FE1DB + //The size of the serial number value published is KUsbStringDescStringMaxSize. The + //USB spec doesn't give a specific max size for the serial number, it just says it is + //a string descriptor, hence it can have size KUsbStringDescStringMaxSize (252 characters). + TInt r = RProperty::Define(KUidSystemCategory,0x101FE1DB,RProperty::EText,KUsbStringDescStringMaxSize); + if(r!=KErrAlreadyExists && r!=KErrNone) + { + User::Leave(r); + } + r = RProperty::Set(KUidSystemCategory,0x101FE1DB,serNum); + User::LeaveIfError(r); + + _printf(_L("Serial number published. Restart USB for change to take effect.\ne.g. Option 1 -> 1 (calls RUsb::Start)\n")); + } + } + +//////////////////////////////////////////////////////////////////////////////// +// Menus etc. below this point +//////////////////////////////////////////////////////////////////////////////// + +TBool SelectStartingTestL(TChar aChar) + { + TBool result = ETrue; + + switch (aChar) + { + case '1': StartUsbL(); break; + case '2': CancelStartingUsbL(EFalse); break; + case '3': CancelStartingUsbL(ETrue); break; + case '4': StartupStressTestL(); break; + case 'q': + case 'Q': + result = EFalse; +// break; // commented out as it's unreachable + default: + _printf(_L("\nInvalid key\n")); + break; + } + return result; + } + +void StartingTestsL() + { + _printf(_L("\nStarting tests\n")); + _printf(_L("--------------\n")); + _printf(_L("Available tests:\n\n")); + _printf(_L("1. Start USB\n")); + _printf(_L("2. Cancel starting USB\n")); + _printf(_L("3. Stop USB while it's starting\n")); + _printf(_L("4. Startup stress test\n")); + _printf(_L("\nSelection (q for main menu): ")); + + TChar ch = (TChar) _getch(); + _printf(_L("\n")); + + TRAP_IGNORE(SelectStartingTestL(ch)); + } + +TBool SelectStoppingTestL(TChar aChar) + { + TBool result = ETrue; + + switch (aChar) + { + case '1': StopUsbSynchronousL(); break; +#ifndef HURRICANE + case '2': StopUsbAsynchronousL(); break; + case '3': CancelStoppingUsbL(EFalse); break; + case '4': CancelStoppingUsbL(ETrue); break; +#endif // HURRICANE + case 'q': + case 'Q': + result = EFalse; +// break; // commented out as it's unreachable + default: + _printf(_L("\nInvalid key\n")); + break; + } + return result; + } + +void StoppingTestsL() + { + _printf(_L("\nStopping tests\n")); + _printf(_L("--------------\n")); + _printf(_L("Available tests:\n\n")); + _printf(_L("1. Stop USB synchronously\n")); +#ifndef HURRICANE + _printf(_L("2. Stop USB asynchronously\n")); + _printf(_L("3. Cancel stopping USB\n")); + _printf(_L("4. Start USB whilst stopping\n")); +#endif // HURRICANE + _printf(_L("\nSelection (q for main menu): ")); + + TChar ch = (TChar) _getch(); + _printf(_L("\n")); + + TRAP_IGNORE(SelectStoppingTestL(ch)); + } + +TBool SelectConcurrencyTestL(TChar aChar) + { + TBool result = ETrue; + + switch (aChar) + { + case '1': StartAThenStopBL(); break; + case '2': StopBWhileAStartingL(); break; + case '3': StartBWhileAStartingL(); break; +#ifndef HURRICANE + case '4': StartBWhileAStoppingL(); break; + case '5': StopBWhileAStoppingL(); break; +#endif // HURRICANE + case 'q': + case 'Q': + result = EFalse; +// break; // commented out as it's unreachable + default: + _printf(_L("\nInvalid key\n")); + break; + } + return result; + } + +void ConcurrencyTestsL() + { + _printf(_L("\nConcurrency tests\n")); + _printf(_L("-----------------\n")); + _printf(_L("Available tests:\n\n")); + _printf(_L("1. Client A starts, then client B stops\n")); + _printf(_L("2. Client B stops while client A is starting\n")); + _printf(_L("3. Client B starts while client A is starting\n")); +#ifndef HURRICANE + _printf(_L("4. Client B starts while client A is stopping\n")); + _printf(_L("5. Client B stops while client A is stopping\n")); +#endif // HURRICANE + _printf(_L("\nSelection (q for main menu): ")); + + TChar ch = (TChar) _getch(); + _printf(_L("\n")); + + TRAP_IGNORE(SelectConcurrencyTestL(ch)); + } + +void SanityTestL() +/** + * Call each API. Just a quick way of sanity-checking the API. + */ + { + _printf(_L("\nQuick sanity check of all APIs\n")); + + RUsb usb; + LEAVEIFERROR(usb.Connect()); + usb.Version(); + + TUsbDeviceState deviceState; + TRequestStatus deviceStateNotStat; + usb.StateNotification(0xFFFF, deviceState, deviceStateNotStat); + usb.StateNotificationCancel(); + User::WaitForRequest(deviceStateNotStat); + if ( deviceStateNotStat != KErrCancel ) + { + LEAVEIFERROR(__LINE__); + } + + usb.Stop(); // get it into a known state + + TUsbServiceState serviceState; + LEAVEIFERROR(usb.GetServiceState(serviceState)); + if ( serviceState != EUsbServiceIdle ) + { + LEAVEIFERROR(__LINE__); + } + TRequestStatus serviceStateNotStat; + usb.ServiceStateNotification(serviceState, serviceStateNotStat); + // Start & Stop & Cancels + TRequestStatus startStat; + usb.Start(startStat); + User::WaitForRequest(startStat); + LEAVEIFERROR(startStat.Int()); + User::WaitForRequest(serviceStateNotStat); + LEAVEIFERROR(serviceStateNotStat.Int()); + if ( serviceState != EUsbServiceStarting ) + { + LEAVEIFERROR(__LINE__); + } + LEAVEIFERROR(usb.GetServiceState(serviceState)); + if ( serviceState != EUsbServiceStarted ) + { + LEAVEIFERROR(__LINE__); + } + usb.Stop(); + usb.StartCancel(); + usb.StopCancel(); + TRequestStatus stopStat; + usb.Stop(stopStat); + User::WaitForRequest(stopStat); + LEAVEIFERROR(stopStat.Int()); + + // Service state + LEAVEIFERROR(usb.GetServiceState(serviceState)); + if ( serviceState != EUsbServiceIdle ) + { + LEAVEIFERROR(__LINE__); + } + LEAVEIFERROR(usb.GetCurrentState(serviceState)); + if ( serviceState != EUsbServiceIdle ) + { + LEAVEIFERROR(__LINE__); + } + usb.ServiceStateNotification(serviceState, serviceStateNotStat); + usb.ServiceStateNotificationCancel(); + User::WaitForRequest(serviceStateNotStat); + if ( serviceStateNotStat != KErrCancel ) + { + LEAVEIFERROR(__LINE__); + } + User::After(1000000); + // Device state + LEAVEIFERROR(usb.GetDeviceState(deviceState)); // need default for Cedar below + if ( deviceState != EUsbDeviceStateUndefined && deviceState != EUsbDeviceStateDefault ) + { + LEAVEIFERROR(__LINE__); + } + usb.DeviceStateNotification(0xFFFF, deviceState, deviceStateNotStat); + usb.DeviceStateNotificationCancel(); + User::WaitForRequest(deviceStateNotStat); + if ( deviceStateNotStat != KErrCancel ) + { + LEAVEIFERROR(__LINE__); + } + usb.DeviceStateNotification(EUsbDeviceStateDefault, deviceState, deviceStateNotStat); + usb.Start(startStat); + User::WaitForRequest(startStat); + LEAVEIFERROR(startStat.Int()); + User::WaitForRequest(deviceStateNotStat); + LEAVEIFERROR(deviceStateNotStat.Int()); // need undefined for Cedar below + if ( deviceState != EUsbDeviceStateDefault && deviceState != EUsbDeviceStateUndefined ) + { + LEAVEIFERROR(__LINE__); + } + User::After(1000000); + LEAVEIFERROR(usb.GetDeviceState(deviceState)); // need default & undefined & configured for Cedar below + if ( deviceState != EUsbDeviceStateSuspended && deviceState != EUsbDeviceStateDefault && deviceState != EUsbDeviceStateUndefined && deviceState != EUsbDeviceStateConfigured) + { + LEAVEIFERROR(__LINE__); + } + // Heap marking + LEAVEIFERROR(usb.__DbgMarkHeap()); + LEAVEIFERROR(usb.__DbgCheckHeap(0)); + LEAVEIFERROR(usb.__DbgMarkEnd(0)); + // NB __DbgFailNext is not checked + usb.Stop(); + usb.Close(); + } + +#ifndef HURRICANE + +TBool SelectMemoryTestL(TChar aChar) + { + TBool result = ETrue; + + switch (aChar) + { + case '1': LEAVEIFERROR(TheUsb.__DbgMarkHeap()); break; + case '2': DbgCheckHeapL(); break; + case '3': DbgMarkEndL(); break; + case '4': DbgFailNextL(); break; + case 'q': + case 'Q': + result = EFalse; +// break; // commented out as it's unreachable + default: + _printf(_L("\nInvalid key\n")); + break; + } + return result; + } + +void MemoryTestsL() + { + _printf(_L("\nMemory tests\n")); + _printf(_L("------------\n")); + _printf(_L("Available tests:\n\n")); + _printf(_L("1. Mark heap\n")); + _printf(_L("2. Check heap\n")); + _printf(_L("3. End marking heap\n")); + _printf(_L("4. Simulate allocation failure\n")); + _printf(_L("\nSelection (q for main menu): ")); + + TChar ch = (TChar) _getch(); + _printf(_L("\n")); + + TRAP_IGNORE(SelectMemoryTestL(ch)); + } + +#endif // HURRICANE + +TBool SelectTestL(TChar aChar) + { + TBool result = ETrue; + + switch (aChar) + { + case '1': StartingTestsL(); break; + case '2': StoppingTestsL(); break; + case '3': MonitorUsbDeviceStateL(); break; + case '4': ConcurrencyTestsL(); break; + case '5': SetUsbSerialNumberL(); break; + case 's': case 'S': SanityTestL(); break; +#ifndef HURRICANE +/* case 'r': RegisterAsPrimaryClientL(); break; + case 'd': DeregisterAsPrimaryClientL(); break; +*/ case 'm': MemoryTestsL(); break; +#endif // HURRICANE + case 'c': case 'C': CloseUsbL(); break; + case 'o': case 'O': OpenUsbL(); break; + case 'q': + case 'Q': + result = EFalse; +// break; // commented out as it's unreachable + default: + _printf(_L("\nInvalid key\n")); + break; + } + return result; + } + +void mainL() + { + // Create the global timer. This is used throughout the code for timing services. + TheTimer.CreateLocal(); + + TInt ret; + +#ifndef __WINS__ + ret = User::LoadLogicalDevice(KUsbLddName); + if ((ret != KErrNone) && (ret != KErrAlreadyExists)) + LEAVE(ret); + + _printf(_L("Loaded USB LDD\n")); +#endif + + ret = StartC32(); + if ((ret != KErrNone) && (ret != KErrAlreadyExists)) + LEAVE(ret); + + _printf(_L("Started C32\n")); + + OpenUsbL(); + + TUsbServiceState serviceState; + + TBool noExit = ETrue; + while (noExit) + { + _printf(_L("\nMain menu\n")); + _printf(_L("---------\n")); + _printf(_L("Available tests:\n\n")); + _printf(_L("1. Starting tests\n")); + _printf(_L("2. Stopping tests\n")); + _printf(_L("3. Monitor USB device state\n")); + _printf(_L("4. Concurrency tests\n")); + _printf(_L("5. Publish Serial Number\n")); + _printf(_L("S. Sanity test- quickly calls all APIs to make sure they don't panic\n")); +#ifndef HURRICANE +/* _printf(_L("R. Register as primary client\n")); + _printf(_L("D. Deregister as primary client\n")); +*/ _printf(_L("M. Memory tests\n")); +#endif // HURRICANE + _printf(_L("C. Close connection to USB Manager\n")); + _printf(_L("O. Connect to USB Manager\n")); + + if (TheUsb.Handle()) + { + _printf(_L("\nConnected to USB ")); + if (ThePrimaryClient) + _printf(_L("as the primary client.\n")); + else + _printf(_L("as a non-primary client.\n")); + + ret = TheUsb.GetCurrentState(serviceState); + if (ret == KErrNone) + PrintUsbServiceState(serviceState); + else + _printf(_L("Couldn't get USB service state (error %d).\n"), ret); + } + else + { + _printf(_L("\nNot connected to USB.\n")); + } + + _printf(_L("\nSelection (q to quit): ")); + + TChar ch = (TChar) _getch(); + _printf(_L("\n")); + + TRAP_IGNORE(noExit = SelectTestL(ch)); + } + + TheCommServ.Close(); + TheUsb.Close(); + } + +void consoleMainL() + { + console=Console::NewL(_L("T_USBMAN"),TSize(KConsFullScreen,KConsFullScreen)); + CleanupStack::PushL(console); + mainL(); + _printf(_L("[ press any key ]")); + _getch(); + CleanupStack::PopAndDestroy(); + } + +GLDEF_C TInt E32Main() + { + __UHEAP_MARK; + CTrapCleanup* cleanupStack=CTrapCleanup::New(); + TRAP_IGNORE(consoleMainL()); + delete cleanupStack; + __UHEAP_MARKEND; + return 0; + }