diff -r 000000000000 -r c9bc50fca66e usbmgmt/usbmgrtest/t_multi_acm/src/t_multiple_acm.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usbmgmt/usbmgrtest/t_multi_acm/src/t_multiple_acm.cpp Tue Feb 02 02:02:59 2010 +0200 @@ -0,0 +1,792 @@ +/* +* 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 program executes all the tests in the ACM CSY Test Specification v 0.1 +* and is to be used in conjunction with the host-side application. +* +*/ + +#include +#include +#include +#include +#include + +LOCAL_D CConsoleBase* console; + +RCommServ TheCommServ; + + +TCommConfig TheConfigBuf; +TCommConfigV01& TheConfig = TheConfigBuf(); + +const TInt KReceiveBufferLength = 4096; +const TInt KMaxAcmPortNameLength = 8; +//_LIT(KUsbCsyName, "ECACM"); +_LIT(KUsbPortName, "ACM::0"); +_LIT(KUsbPortNameAcm1, "ACM::1"); + +_LIT(KUsbLddName, "EUSBC"); + +#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)) + +// A define for stack-based buffers +#define MAX_BUFFER_SIZE 1024 + +// A bigger buffer on the heap +#define MAX_HEAP_BUFFER_SIZE 1024*8 +TBuf8 readBigBuf; + +// A timer for use by several of the tests +RTimer timer; + +void VerboseLeaveL(TInt aError, TInt aLineNum, const TDesC8& aFileName, const TDesC8& aCode) +/** + * For bombing out usefully. + */ + { + 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("\nERROR (%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) +/** + * For bombing out usefully if there's an error. + */ + { + 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++; + } + } + } + + +////////////////////////////////////////////////////////////////////////////////////////////// +/** + * loopback From a Port input by the user to abother port- + * ACM::1 KUsbPortNameAcm1 to ACM::0 KUsbPortName by default + */ + +void ReadLoopbackFromPortAToPortBTestL() + { + + TRequestStatus consoleStatus; + TRequestStatus status; + RComm portIN; + RComm portOut; + + _printf(_L("Enter the packet size:")); + TBufC<8> buf; + TPtr ptr (buf.Des()); + ReadString(ptr); + + TLex input(buf); + + TInt pktlen = 0; + while ((input.Peek()).IsDigit()) { + pktlen = 10*pktlen + (input.Get()) - '0'; + } + + // Get port names + _printf(_L("\nEnter acm port name as loopback INPUT: (ex ACM::1):")); + TBufC portINName; + TPtr portINNamePtr (portINName.Des()); + ReadString(portINNamePtr); + if ( portINNamePtr.Length() == 0 ) + { + portINName= KUsbPortNameAcm1; + } + + _printf(_L("\nEnter acm port name as loopback OUTPUT: (ex ACM::0):")); + TBufC portOutName; + TPtr portOutNamePtr (portOutName.Des()); + ReadString(portOutNamePtr); + if ( portOutNamePtr.Length() == 0 ) + { + portOutName = KUsbPortName; + } + + + _printf(_L("\n----------------------------------------\n")); + _printf(_L("This test listens for data on the ACM port: ")); + _printf(portINName); + _printf(_L("\nwrites anything it receives on the ACM port: ")); + _printf(portOutName); + _printf(_L("\nPress any key to quit.\n")); + _printf(_L("----------------------------------------\n\n")); + + LEAVEIFERROR(portIN.Open(TheCommServ, portINName, ECommExclusive, ECommRoleDCE)); + CleanupClosePushL(portIN); + + LEAVEIFERROR(portOut.Open(TheCommServ, portOutName, ECommExclusive, ECommRoleDCE)); + CleanupClosePushL(portOut); + + _printf(_L("Setting handshaking & receive buffer length\n")); + + portIN.SetConfig(TheConfigBuf); + portIN.SetReceiveBufferLength(KReceiveBufferLength); + portOut.SetConfig(TheConfigBuf); + portOut.SetReceiveBufferLength(KReceiveBufferLength); + + _printf(_L("loopback received data\n")); + + console->Read(consoleStatus); + + FOREVER + { + portIN.Read(status, readBigBuf, pktlen); + + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + portIN.ReadCancel(); + break; + } + + portOut.Write(status, readBigBuf); + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + // need to cancel the read to avoid a CBase-77 panic! + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + portOut.WriteCancel(); + break; + } + } + + portOut.WriteCancel(); + + _printf(_L("\nTest complete\n")); + + CleanupStack::PopAndDestroy(2); // portA , portOut + + } + + +////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Original loopback test - uses Read(). + */ + +void ReadLoopbackTestL() + { + + TRequestStatus consoleStatus; + TRequestStatus status; + RComm port; + RComm port2; + + _printf(_L("Enter the packet size:")); + TBufC<8> buf; + TPtr ptr (buf.Des()); + ReadString(ptr); + + TLex input(buf); + + TInt pktlen = 0; + while ((input.Peek()).IsDigit()) { + pktlen = 10*pktlen + (input.Get()) - '0'; + } + + _printf(_L("\n----------------------------------------\n")); + _printf(_L("This test listens for data on the ACM\n")); + _printf(_L("port and echoes anything it receives\n")); + _printf(_L("back to the PC. Press any key to quit.\n")); + _printf(_L("----------------------------------------\n\n")); + + LEAVEIFERROR(port.Open(TheCommServ, KUsbPortName, ECommExclusive, ECommRoleDCE)); + CleanupClosePushL(port); + + LEAVEIFERROR(port2.Open(TheCommServ, _L("ACM::1"), ECommExclusive, ECommRoleDCE)); + CleanupClosePushL(port2); + + _printf(_L("Setting handshaking & receive buffer length\n")); + + port.SetConfig(TheConfigBuf); + port.SetReceiveBufferLength(KReceiveBufferLength); + port2.SetConfig(TheConfigBuf); + port2.SetReceiveBufferLength(KReceiveBufferLength); + + _printf(_L("Echoing received data\n")); + + + + + + console->Read(consoleStatus); + + FOREVER + { + port.Read(status, readBigBuf, pktlen); + + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + port.ReadCancel(); + break; + } + + port.Write(status, readBigBuf); + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + // need to cancel the read to avoid a CBase-77 panic! + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + port.WriteCancel(); + break; + } + } + + + console->Read(consoleStatus); + + FOREVER + { + port2.Read(status, readBigBuf, pktlen); + + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + port2.ReadCancel(); + break; + } + + port2.Write(status, readBigBuf); + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + // need to cancel the read to avoid a CBase-77 panic! + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + port2.WriteCancel(); + break; + } + } + + + _printf(_L("\nTest complete\n")); + + CleanupStack::PopAndDestroy(2); // port , port2 + + } + +/** + * Original loopback test - uses ReadOneOrMore(). + */ + +void LoopbackTestL() + { + TRequestStatus consoleStatus; + TRequestStatus status; + RComm port; + + _printf(_L("\n----------------------------------------\n")); + _printf(_L("This test listens for data on the ACM\n")); + _printf(_L("port and echoes anything it receives\n")); + _printf(_L("back to the PC. Press any key to quit.\n")); + _printf(_L("----------------------------------------\n\n")); + + LEAVEIFERROR(port.Open(TheCommServ, KUsbPortName, ECommExclusive, ECommRoleDCE)); + CleanupClosePushL(port); + + _printf(_L("Setting handshaking & receive buffer length\n")); + + port.SetConfig(TheConfigBuf); + port.SetReceiveBufferLength(KReceiveBufferLength); + + _printf(_L("Echoing received data\n")); + + TBuf8<256> readBuf; + + console->Read(consoleStatus); + + FOREVER + { + port.ReadOneOrMore(status, readBuf); + + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + // need to cancel the read to avoid a CBase-77 panic! + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + port.ReadCancel(); + break; + } + + port.Write(status, readBuf); + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + // need to cancel the read to avoid a CBase-77 panic! + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + port.WriteCancel(); + break; + } + } + + _printf(_L("\nTest complete\n")); + + CleanupStack::PopAndDestroy(); // port + } + +void ReadWithTerminatorsLoopbackTestL() + { + TRequestStatus consoleStatus; + TRequestStatus status; + RComm port; + + // Get terminator characters + _printf(_L("Enter the terminator characters (up to %d):"), KConfigMaxTerminators); + TBufC termbuf; + TPtr termptr (termbuf.Des()); + ReadString(termptr); + TText8 terminators[KConfigMaxTerminators]; + if ( termptr.Length() == 0 ) + { + _printf(_L("\nno terminators given- not running test")); + return; + } + TUint termCount = 0; + TUint ii; + for ( ii = 0 ; ii < (TUint)termptr.Length() ; ii++ ) + { + termCount++; + terminators[ii] = (TText8)termptr[ii]; + } + + _printf(_L("\nEnter the packet size:")); + TBufC<8> buf; + TPtr ptr (buf.Des()); + ReadString(ptr); + + TLex input(buf); + + TInt pktlen = 0; + while ((input.Peek()).IsDigit()) { + pktlen = 10*pktlen + (input.Get()) - '0'; + } + + _printf(_L("\n----------------------------------------\n")); + _printf(_L("This test listens for data on the ACM\n")); + _printf(_L("port and echoes anything it receives\n")); + _printf(_L("back to the PC. Press any key to quit.\n")); + _printf(_L("----------------------------------------\n\n")); + + LEAVEIFERROR(port.Open(TheCommServ, KUsbPortName, ECommExclusive, ECommRoleDCE)); + CleanupClosePushL(port); + + _printf(_L("Setting handshaking & receive buffer length\n")); + + // Set the config, including terminator characters. + TCommConfig configBuf; + TCommConfigV01& config = configBuf(); + port.Config(configBuf); + config.iTerminatorCount = termCount; + for ( ii = 0 ; ii < termCount ; ii++ ) + { + config.iTerminator[ii] = terminators[ii]; + } + LEAVEIFERROR(port.SetConfig(configBuf)); + + port.SetReceiveBufferLength(KReceiveBufferLength); + + _printf(_L("Echoing received data\n")); + + console->Read(consoleStatus); + + TBuf8<256> readBuf; + + FOREVER + { + port.Read(status, readBuf, pktlen); + + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + port.ReadCancel(); + break; + } + + port.Write(status, readBuf); + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + // need to cancel the read to avoid a CBase-77 panic! + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + port.WriteCancel(); + break; + } + } + + _printf(_L("\nTest complete\n")); + + CleanupStack::PopAndDestroy(); // port + } + + + +void AcmLoopback_TestL() +/** + * Runs the test as specified in the ACM unit test specification. + */ + { + TRequestStatus consoleStatus; + TRequestStatus status; + RComm port; + + _printf(_L("\n----------------------------------------\n")); + _printf(_L("This test listens for data on the ACM\n")); + _printf(_L("port and echoes anything it receives\n")); + _printf(_L("back to the PC. Press any key to quit.\n")); + _printf(_L("----------------------------------------\n\n")); + + LEAVEIFERROR(port.Open(TheCommServ, KUsbPortName, ECommExclusive, ECommRoleDCE)); + CleanupClosePushL(port); + + _printf(_L("Setting handshaking & receive buffer length\n")); + + port.SetConfig(TheConfigBuf); + port.SetReceiveBufferLength(KReceiveBufferLength); + + _printf(_L("Echoing received data\n")); + + TBuf8<1024> readBuf; + + console->Read(consoleStatus); + + FOREVER + { + port.ReadOneOrMore(status, readBuf); + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + // need to cancel the read to avoid a CBase-77 panic! + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + port.ReadCancel(); + break; + } + + port.Write(status, readBuf); + User::WaitForRequest(status, consoleStatus); + + if (consoleStatus == KRequestPending) + { + if (status != KErrNone) + { + // need to cancel the read to avoid a CBase-77 panic! + console->ReadCancel(); + LEAVE(status.Int()); + } + } + else + { + port.WriteCancel(); + break; + } + + _printf(_L(".")); + } + + _printf(_L("\nTest complete\n")); + + CleanupStack::PopAndDestroy(); // port + } + +void SetHandshakingL() +/** + * This function allows the user to select a new handshaking mode. + */ + { + RComm port; + + TCommCaps capsBuf; + TCommCapsV01& caps = capsBuf(); + + LEAVEIFERROR(port.Open(TheCommServ, KUsbPortName, ECommExclusive, ECommRoleDCE)); + CleanupClosePushL(port); + + port.Caps(capsBuf); + _printf(_L("\nPort handshaking capabilities: 0x%X\n"), caps.iHandshake); + _printf(_L("Current handshaking options: 0x%X\n"), TheConfig.iHandshake); + + _printf(_L("\nHandshaking options:\n")); + _printf(_L("1. No handshaking\n")); + _printf(_L("2. Toggle Xon/Xoff\n")); + _printf(_L("3. Toggle obey CTS\n")); + _printf(_L("4. Toggle obey DSR / free RTS\n")); + _printf(_L("5. Toggle write buffered complete\n")); + + TInt key = (TInt) _getch(); + + switch (key) + { + case '1': + TheConfig.iHandshake = 0; + break; + case '2': + TheConfig.iHandshake ^= KConfigObeyXoff; + TheConfig.iHandshake ^= KConfigSendXoff; + break; + case '3': + TheConfig.iHandshake ^= KConfigObeyCTS; + break; + case '4': + TheConfig.iHandshake ^= KConfigObeyDSR; + TheConfig.iHandshake ^= KConfigFreeRTS; + break; + case '5': + TheConfig.iHandshake ^= KConfigWriteBufferedComplete; + break; + default: + break; + } + + LEAVEIFERROR(port.SetConfig(TheConfigBuf)); + + _printf(_L("Handshaking options now: 0x%X\n"), TheConfig.iHandshake); + + CleanupStack::PopAndDestroy(); + } + + +void mainL() +/** + * This function controls test execution as directed by the user. + */ + { + char ch; + + TInt ret = User::LoadLogicalDevice(KUsbLddName); + if ((ret != KErrNone) && (ret != KErrAlreadyExists)) + LEAVE(ret); + + _printf(_L("Loaded USB LDD\n")); + + LEAVEIFERROR(TheCommServ.Connect()); + _printf(_L("Connected to C32\n")); + + RComm port; + + // The port's configuration seems to be junk at the beginning, so we set it to known values. + + TheConfig.iRate = EBps115200; + TheConfig.iDataBits = EData8; + TheConfig.iStopBits = EStop1; + TheConfig.iParity = EParityNone; + TheConfig.iHandshake = 0; + TheConfig.iTerminatorCount = 0; + + LEAVEIFERROR(port.Open(TheCommServ, KUsbPortNameAcm1, ECommExclusive, ECommRoleDCE)); + CleanupClosePushL(port); + + port.SetConfig(TheConfigBuf); + _printf(_L("----------------------------------------\n")); + _printf(_L("Initial port config:\n")); + _printf(_L(" Rate: %d bps\n"), TheConfig.iRate); + _printf(_L(" Data bits: %d. Parity type: %d. Stop bits: %d\n"), + TheConfig.iStopBits, TheConfig.iParity, TheConfig.iStopBits); + _printf(_L(" Handshaking options: 0x%X\n"), TheConfig.iHandshake); + _printf(_L("----------------------------------------\n\n")); + + CleanupStack::PopAndDestroy(); // port + + + TBool noExit = ETrue; + while (noExit) + { + _printf(_L("\nAvailable tests:\n\n")); + _printf(_L("1. Read loopback from ACM0->ACM1 test\n")); + _printf(_L("\nSelection (x to exit): ")); + + ch = (char) _getch(); + _printf(_L("\n")); + switch (ch) + { + case '1': ReadLoopbackFromPortAToPortBTestL(); break; + case 'x': + case 'X': noExit = EFalse; break; + default: _printf(_L("\nInvalid key\n")); break; + } + } + TheCommServ.Close(); + } + +void consoleMainL() +/** + * Create a console and run mainL(). + */ + { + console=Console::NewL(_L("T_ACM"),TSize(KConsFullScreen,KConsFullScreen)); + CleanupStack::PushL(console); + mainL(); + _printf(_L("[ press any key ]")); + _getch(); + CleanupStack::PopAndDestroy(); + } + +GLDEF_C TInt E32Main() +/** + * Runs the test as specified in the ACM unit test specification. + */ + { + __UHEAP_MARK; + CTrapCleanup* cleanupStack=CTrapCleanup::New(); + + // create the timer for use during some of the tests + timer.CreateLocal(); + + TRAP_IGNORE(consoleMainL()); + delete cleanupStack; + __UHEAP_MARKEND; + return 0; + } +