sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\device\t_modem1.cpp sl@0: // Test program for PC Card Serial Port Driver - Requires Dacom GoldCard Modem. sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: class RComm : public RBusDevComm sl@0: { sl@0: public: sl@0: TInt WriteS(const TDesC8& aDes); sl@0: }; sl@0: sl@0: const TInt KBlockSize=256; sl@0: // Block size Line rate sl@0: const TInt KBlocksShort=4; // 4*256=1K - <1200 sl@0: const TInt KBlocksMedium=12; // 12*256=3K - <4800 sl@0: const TInt KBlocksLong=64; // 64*256=16K - <28800 sl@0: const TInt KBlocksVeryLong=128; // 128*256=32K - 28800 sl@0: sl@0: enum TLineRate {EV21_300,EBell103_300,EV22_1200,EBell212_1200,EV22bis_2400, sl@0: EV32_4800,EV32_9600,EV32bis_14400,EV34_28800,ELineRateEnd}; sl@0: const TInt KMaxLineRates=ELineRateEnd; sl@0: const TInt KStandardRxBufferSize=0x400; sl@0: sl@0: #if !defined (__WINS__) sl@0: #define PDD_NAME _L("EUARTn") sl@0: #define LDD_NAME _L("ECOMM") sl@0: #else sl@0: #define PDD_NAME _L("ECDRV.PDD") sl@0: #define LDD_NAME _L("ECOMM.LDD") sl@0: #endif sl@0: sl@0: LOCAL_D RTest test(_L("T_MODEM1")); sl@0: LOCAL_D TInt LineModeData[KMaxLineRates]={0,64,1,69,2,9,9,10,11}; sl@0: LOCAL_D TInt LineRateData[KMaxLineRates]={300,300,1200,1200,2400,4800,9600,14400,28800}; sl@0: LOCAL_D TInt LineConnectData[KMaxLineRates]={1200,1200,1200,1200,2400,4800,9600,14400,28800}; sl@0: LOCAL_D RComm *theSerialPort; sl@0: sl@0: sl@0: TInt RComm::WriteS(const TDesC8& aDes) sl@0: // sl@0: // Syncronous write sl@0: // sl@0: { sl@0: sl@0: TRequestStatus s; sl@0: Write(s,aDes,aDes.Length()); sl@0: User::WaitForRequest(s); sl@0: return(s.Int()); sl@0: } sl@0: sl@0: LOCAL_C TPtrC BaudRateInText(TBps aRate) sl@0: // sl@0: // Convert into Baudrate text sl@0: // sl@0: { sl@0: sl@0: switch (aRate) sl@0: { sl@0: case EBps50: return(_L("50")); break; sl@0: case EBps75: return(_L("75")); break; sl@0: case EBps110: return(_L("110")); break; sl@0: case EBps134: return(_L("134")); break; sl@0: case EBps150: return(_L("150")); break; sl@0: case EBps300: return(_L("300")); break; sl@0: case EBps600: return(_L("600")); break; sl@0: case EBps1200: return(_L("1200")); break; sl@0: case EBps1800: return(_L("1800")); break; sl@0: case EBps2000: return(_L("2000")); break; sl@0: case EBps2400: return(_L("2400")); break; sl@0: case EBps3600: return(_L("3600")); break; sl@0: case EBps4800: return(_L("4800")); break; sl@0: case EBps7200: return(_L("7200")); break; sl@0: case EBps9600: return(_L("9600")); break; sl@0: case EBps19200: return(_L("19200")); break; sl@0: case EBps38400: return(_L("38400")); break; sl@0: case EBps57600: return(_L("57600")); break; sl@0: case EBps115200: return(_L("115000")); break; sl@0: default: return(_L("Unknown")); break; sl@0: } sl@0: } sl@0: sl@0: LOCAL_C TInt TranslateCrLf(TDes8 &aDes) sl@0: // sl@0: // Search for CR/LF characters in a string and replace them with sl@0: // '\r' '\n' format. Also replaces unprintable characters with "?" sl@0: // sl@0: { sl@0: sl@0: TText8 buf[KBlockSize]; sl@0: TText8 *pS=(TText8*)aDes.Ptr(); sl@0: TText8 *pSE=pS+aDes.Size(); sl@0: TText8 *pT=&buf[0]; sl@0: TText8 *pTMax=pT+(KBlockSize-1); sl@0: for (;pS=pTMax) sl@0: return(KErrTooBig); sl@0: if (*pS=='\xD'||*pS=='\xA') sl@0: { sl@0: *pT++='\\'; sl@0: *pT=(*pS=='\xD')?'r':'n'; sl@0: } sl@0: else if (((TChar)*pS).IsPrint()) sl@0: *pT=*pS; sl@0: else sl@0: *pT='\?'; sl@0: } sl@0: *pT=0; sl@0: if ((pT-&buf[0])>aDes.MaxLength()) sl@0: return(KErrTooBig); sl@0: aDes.Copy(&buf[0]); sl@0: return(KErrNone); sl@0: } sl@0: /* ??? sl@0: LOCAL_C void PrintBuf(TDes8 &aBuf) sl@0: // sl@0: // Print the contents of a buffer sl@0: // sl@0: { sl@0: sl@0: TInt len=aBuf.Length(); sl@0: for (TInt i=0;i<=len/8;i++) sl@0: { sl@0: test.Printf(_L("%4d: "),i*8); sl@0: sl@0: for (TInt j=0;j<8;j++) sl@0: { sl@0: if ((i*8)+j>=len) sl@0: break; sl@0: TInt v=aBuf[(i*8)+j]; sl@0: test.Printf(_L("%02x "),v); sl@0: } sl@0: test.Printf(_L("\n\r")); sl@0: } sl@0: } sl@0: */ sl@0: LOCAL_C void testLoopBack(TLineRate aLineRate,TBps aBaudRate) sl@0: // sl@0: // Perform an analogue loopback test at the specified linerate sl@0: // sl@0: { sl@0: sl@0: TInt err; sl@0: TBuf<64> b; sl@0: TPtrC bd=BaudRateInText(aBaudRate); sl@0: b.Format(_L("Loopback test(%S)"),&bd); sl@0: test.Start(b); sl@0: sl@0: TBuf8 txBuf; sl@0: theSerialPort->ResetBuffers(); sl@0: txBuf.Format(_L8("AT&F+MS=%d,0,%d,%d\\N0&K3&D2M0\r"),LineModeData[aLineRate],LineRateData[aLineRate],LineRateData[aLineRate]); sl@0: test(theSerialPort->WriteS(txBuf)==KErrNone); sl@0: sl@0: TBuf8 rxBuf; sl@0: User::After(2000000); // 2Secs sl@0: err=theSerialPort->QueryReceiveBuffer(); sl@0: test(err>0); sl@0: rxBuf.SetLength(err); sl@0: TRequestStatus rxStat; sl@0: theSerialPort->ReadOneOrMore(rxStat,rxBuf); sl@0: User::WaitForRequest(rxStat); sl@0: // test.Printf(_L(" Rx(%d):"),rxStat); // ??? sl@0: test(rxStat==KErrNone); sl@0: txBuf.Append(_L("\r\nOK\r\n")); sl@0: err=rxBuf.Compare(txBuf); sl@0: // test(TranslateCrLf(rxBuf)==KErrNone); // ??? sl@0: // test.Printf(_L(" %S\r\n"),&rxBuf); // ??? sl@0: test(err==0); sl@0: sl@0: test.Next(_L("Get loopback")); sl@0: txBuf.Format(_L8("AT&T1\r")); sl@0: test(theSerialPort->WriteS(txBuf)==KErrNone); sl@0: User::After(5000000); // 5Secs sl@0: err=theSerialPort->QueryReceiveBuffer(); sl@0: test(err>0); sl@0: rxBuf.SetLength(err); sl@0: theSerialPort->ReadOneOrMore(rxStat,rxBuf); sl@0: User::WaitForRequest(rxStat); sl@0: test.Printf(_L(" Rx(%d):"),rxStat); sl@0: test(rxStat==KErrNone); sl@0: txBuf.AppendFormat(_L8("\r\nCONNECT %d\r\n"),LineConnectData[aLineRate]); sl@0: err=rxBuf.Compare(txBuf); sl@0: test(TranslateCrLf(rxBuf)==KErrNone); sl@0: test.Printf(_L(" %S\r\n"),&rxBuf); // Print what we got back (without CR/LF etc). sl@0: // Sometimes get extra character as modem goes on-line so just look for command echo + connect sl@0: test(err>=0); sl@0: User::After(2000000); // 2Secs sl@0: sl@0: TInt totalBlocksToTransfer; sl@0: if (aBaudRateWrite(txStat,txBuf,KBlockSize); sl@0: TInt txBlks=(totalBlocksToTransfer-1); sl@0: rxBuf.Fill(0,KBlockSize); sl@0: theSerialPort->Read(rxStat,rxBuf,KBlockSize); sl@0: TInt rxBlks=0; sl@0: TRequestStatus tStat; sl@0: RTimer tim; sl@0: test(tim.CreateLocal()==KErrNone); sl@0: tim.After(tStat,40000000); // 40Secs sl@0: test.Printf(_L(">")); sl@0: FOREVER sl@0: { sl@0: User::WaitForAnyRequest(); sl@0: if (tStat!=KRequestPending) sl@0: { sl@0: // test.Printf(_L("t")); // Timed out sl@0: theSerialPort->ReadCancel(); // Cancel serial read sl@0: User::WaitForRequest(rxStat); sl@0: if (txBlks>0) sl@0: { sl@0: theSerialPort->WriteCancel(); // Cancel serial write sl@0: User::WaitForRequest(txStat); sl@0: } sl@0: loopBackFail=KErrTimedOut; // Test failed sl@0: break; sl@0: } sl@0: else if (rxStat!=KRequestPending) sl@0: { sl@0: // test.Printf(_L("r")); // Serial rx request complete sl@0: if (rxStat!=0) sl@0: { sl@0: loopBackFail=rxStat.Int(); // Test failed sl@0: goto endSerial; sl@0: } sl@0: for (i=0;iRead(rxStat,rxBuf,KBlockSize); sl@0: } sl@0: else sl@0: { sl@0: loopBackFail=KErrNone; sl@0: endSerial: sl@0: tim.Cancel(); // Cancel timer request. sl@0: User::WaitForRequest(tStat); sl@0: if (txBlks>0) sl@0: { sl@0: theSerialPort->WriteCancel(); // Cancel serial write sl@0: User::WaitForRequest(txStat); sl@0: } sl@0: break; sl@0: } sl@0: } sl@0: else if (txStat!=KRequestPending) sl@0: { sl@0: // test.Printf(_L("s")); // Serial tx request complete sl@0: if (txBlks>0) sl@0: { sl@0: theSerialPort->Write(txStat,txBuf,KBlockSize); sl@0: test.Printf(_L(">")); sl@0: txBlks--; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // test.Printf(_L("?")); // Stray signal - cancel everything sl@0: theSerialPort->ReadCancel(); // Cancel serial read sl@0: User::WaitForRequest(rxStat); sl@0: tim.Cancel(); // Cancel timer request. sl@0: User::WaitForRequest(tStat); sl@0: if (txBlks>0) sl@0: { sl@0: theSerialPort->WriteCancel(); // Cancel serial write sl@0: User::WaitForRequest(txStat); sl@0: } sl@0: loopBackFail=KErrDied; sl@0: break; sl@0: } sl@0: } sl@0: test.Printf(_L(" (%d)\r\n"),loopBackFail); sl@0: // !!! At this point RTS may or may not be asserted following the write cancel. The sl@0: // following seems necessary to make sure RTS is asserted so any remaining Rx data sl@0: // can be received.and thrown away sl@0: User::After(2000000); sl@0: theSerialPort->ResetBuffers(); sl@0: User::After(1000000); // Wait 1Secs for any remaining Rx data sl@0: tim.Close(); sl@0: sl@0: test.Next(_L("Disconnect")); sl@0: theSerialPort->ResetBuffers(); // Through away any remaining Rx data. sl@0: txBuf.Format(_L8("+++")); sl@0: test(theSerialPort->WriteS(txBuf)==KErrNone); sl@0: User::After(2000000); // 2Secs sl@0: err=theSerialPort->QueryReceiveBuffer(); sl@0: test(err>0); sl@0: rxBuf.SetLength(err); sl@0: theSerialPort->ReadOneOrMore(rxStat,rxBuf); sl@0: User::WaitForRequest(rxStat); sl@0: test(rxStat==KErrNone); sl@0: txBuf.Append(_L("\r\nOK\r\n")); sl@0: err=rxBuf.Compare(txBuf); sl@0: // test(TranslateCrLf(rxBuf)==KErrNone); // ??? sl@0: // test.Printf(_L(" %S\r\n"),&rxBuf); // ??? sl@0: test(err==0); sl@0: sl@0: txBuf.Format(_L8("ATH0\r")); sl@0: test(theSerialPort->WriteS(txBuf)==KErrNone); sl@0: User::After(4000000); // 4Secs sl@0: err=theSerialPort->QueryReceiveBuffer(); sl@0: test(err>0); sl@0: rxBuf.SetLength(err); sl@0: theSerialPort->ReadOneOrMore(rxStat,rxBuf); sl@0: User::WaitForRequest(rxStat); sl@0: test(rxStat==KErrNone); sl@0: txBuf.Append(_L("\r\nOK\r\n")); sl@0: err=rxBuf.Compare(txBuf); sl@0: // test(TranslateCrLf(rxBuf)==KErrNone); // ??? sl@0: // test.Printf(_L(" %S\r\n"),&rxBuf); // ??? sl@0: test(err==0); sl@0: sl@0: test.Next(_L("Check result")); sl@0: test(loopBackFail==KErrNone || loopBackFail==KErrCorrupt); // !!!Ignore compare fails for now!!! sl@0: // test(loopBackFail==KErrNone); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: LOCAL_C void testAllLineRates(TBps aRate) sl@0: // sl@0: // Perform loopback test at the specified baudrate in as many line modes that sl@0: // are supported at this baudrate sl@0: // sl@0: { sl@0: sl@0: test.Start(_L("Setting baudrate")); sl@0: TCommConfig cBuf; sl@0: TCommConfigV01 &c=cBuf(); sl@0: theSerialPort->Config(cBuf); sl@0: c.iRate=aRate; sl@0: c.iDataBits=EData8; sl@0: c.iStopBits=EStop1; sl@0: c.iParity=EParityNone; sl@0: c.iHandshake=KConfigObeyCTS; sl@0: // c.iHandshake=0; sl@0: test(theSerialPort->SetConfig(cBuf)==KErrNone); sl@0: sl@0: if (aRate>=EBps38400) sl@0: { sl@0: test.Next(_L("Testing at V.34-28800")); sl@0: testLoopBack(EV34_28800,aRate); sl@0: } sl@0: sl@0: if (aRate>=EBps19200) sl@0: { sl@0: test.Next(_L("Testing at V.32bis-14400")); sl@0: testLoopBack(EV32bis_14400,aRate); sl@0: } sl@0: sl@0: if (aRate>=EBps9600) sl@0: { sl@0: test.Next(_L("Testing at V.32-9600")); sl@0: testLoopBack(EV32_9600,aRate); sl@0: } sl@0: sl@0: // if (aRate>=EBps4800) sl@0: // { sl@0: // test.Next(_L("Testing at V.32-4800")); sl@0: // testLoopBack(EV32_4800,aRate); sl@0: // } sl@0: sl@0: if (aRate>=EBps2400) sl@0: { sl@0: test.Next(_L("Testing at V.22bis-2400")); sl@0: testLoopBack(EV22bis_2400,aRate); sl@0: } sl@0: sl@0: // if (aRate>=EBps1200) sl@0: // { sl@0: // test.Next(_L("Testing at Bell212-1200")); sl@0: // testLoopBack(EBell212_1200,aRate); sl@0: // } sl@0: sl@0: // if (aRate>=EBps1200) sl@0: // { sl@0: // test.Next(_L("Testing at V.22-1200")); sl@0: // testLoopBack(EV22_1200,aRate); sl@0: // } sl@0: sl@0: // test.Next(_L("Testing at Bell103-300")); sl@0: // testLoopBack(EBell103_300,aRate); sl@0: sl@0: test.Next(_L("Testing at V.21-300")); sl@0: testLoopBack(EV21_300,aRate); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: // test.SetLogged(EFalse); // Turn off serial port debugging! sl@0: sl@0: TInt r; sl@0: test.Title(); sl@0: sl@0: test.Start(_L("PC Card Modem Test Program")); sl@0: sl@0: RProcess proc; sl@0: TBuf <0x100> cmd; sl@0: proc.CommandLine(cmd); sl@0: sl@0: // First parameter (if present) sets the serial port number sl@0: TInt port=0; sl@0: if ((cmd.Length()>0) && (cmd[0]>='1' && cmd[0]<='4')) sl@0: port=(TInt)(cmd[0]-'0'); sl@0: sl@0: // 2nd parameter (if present) sets the start speed sl@0: // (4=115K,3=57600,2=38400,1=19200,0=9600) sl@0: TInt startSpeed=4; sl@0: if ((cmd.Length()>3) && (cmd[2]>='0' && cmd[2]<='4')) sl@0: startSpeed=(TInt)(cmd[2]-'0'); sl@0: sl@0: test.Next(_L("Load Device Drivers")); sl@0: TBuf<10> pddName=PDD_NAME; sl@0: #if !defined (__WINS__) sl@0: pddName[5]=(TText)('1'+port); sl@0: TInt muid=0; sl@0: if (HAL::Get(HAL::EMachineUid, muid)==KErrNone) sl@0: { sl@0: // Brutus uses EUART4 for both COM3 and COM4 sl@0: if (muid==HAL::EMachineUid_Brutus && port==4) sl@0: pddName[5]=(TText)'4'; sl@0: } sl@0: #endif sl@0: r=User::LoadPhysicalDevice(pddName); sl@0: test(r==KErrNone||r==KErrAlreadyExists); sl@0: r=User::LoadLogicalDevice(LDD_NAME); sl@0: test(r==KErrNone||r==KErrAlreadyExists); sl@0: sl@0: test.Next(_L("Open serial port")); sl@0: theSerialPort=new RComm; sl@0: test(theSerialPort!=NULL); sl@0: r=theSerialPort->Open(port); sl@0: test(r==KErrNone); sl@0: // TCommCaps capsBuf; sl@0: // TCommCapsV01& caps=capsBuf(); sl@0: // theSerialPort->Caps(capsBuf); sl@0: sl@0: // Check that the driver powering sequence has completed successfully by sl@0: // issueing a few simple driver control functions. sl@0: test.Next(_L("Modem power tests")); sl@0: test(theSerialPort->SetReceiveBufferLength(KStandardRxBufferSize)==KErrNone); sl@0: r=theSerialPort->ReceiveBufferLength(); sl@0: // test.Printf(_L("(%d)"),r); // ??? sl@0: test(r==KStandardRxBufferSize); sl@0: r=(TInt)theSerialPort->Signals(); sl@0: // test.Printf(_L("(%d)"),r); // ??? sl@0: test(r>=0); sl@0: sl@0: RTimer timer; sl@0: TRequestStatus rs; sl@0: test(timer.CreateLocal()==KErrNone); sl@0: TTime tim; sl@0: tim.HomeTime(); sl@0: tim+=TTimeIntervalSeconds(8); sl@0: timer.At(rs,tim); sl@0: UserHal::SwitchOff(); sl@0: User::WaitForRequest(rs); sl@0: test(rs.Int()==KErrNone); sl@0: sl@0: r=theSerialPort->ReceiveBufferLength(); sl@0: // test.Printf(_L("(%d)"),r); // ??? sl@0: test(r==KStandardRxBufferSize); sl@0: r=(TInt)theSerialPort->Signals(); sl@0: // test.Printf(_L("(%d)"),r); // ??? sl@0: test(r>=0); sl@0: User::After(2000000); // 2Secs !!! sl@0: sl@0: if (startSpeed>=4) sl@0: { sl@0: test.Next(_L("Testing at 115K")); sl@0: testAllLineRates(EBps115200); sl@0: } sl@0: sl@0: if (startSpeed>=3) sl@0: { sl@0: test.Next(_L("Testing at 57600")); sl@0: testAllLineRates(EBps57600); sl@0: } sl@0: sl@0: if (startSpeed>=2) sl@0: { sl@0: test.Next(_L("Testing at 38400")); sl@0: testAllLineRates(EBps38400); sl@0: } sl@0: sl@0: if (startSpeed>=1) sl@0: { sl@0: test.Next(_L("Testing at 19200")); sl@0: testAllLineRates(EBps19200); sl@0: } sl@0: sl@0: test.Next(_L("Testing at 9600")); sl@0: testAllLineRates(EBps9600); sl@0: sl@0: test.Next(_L("Close serial port")); sl@0: theSerialPort->Close(); sl@0: delete theSerialPort; sl@0: test.End(); sl@0: return(KErrNone); sl@0: } sl@0: