diff -r 000000000000 -r 3da2a79470a7 testexecmgmt/ucc/Source/UCCSDeviceControl/CSerialTransport.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testexecmgmt/ucc/Source/UCCSDeviceControl/CSerialTransport.cpp Mon Mar 08 15:04:18 2010 +0800 @@ -0,0 +1,372 @@ +/* +* Copyright (c) 2005-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: +* Local Includes +* +*/ + + + +#include "assert.h" +#include "CSerialTransport.h" + +/************************************************************************************** + * + * Definitions + * + *************************************************************************************/ +_LIT(LDD_NAME,"ECOMM"); +#ifdef __WINS__ +_LIT(PDD_NAME,"ECDRV"); +#else +_LIT(PDD_NAME,"EUART1"); +#endif + +#define KMaxTimeoutRetries (0x0FFFFFFF) +#define KWriteTimeout 50000000 + +/******************************************************************************** + * + * Macro functions + * + ********************************************************************************/ + +/************************************************************************************** + * + * CSerialTransport - Construction + * + *************************************************************************************/ +CSerialTransport* CSerialTransport::NewL( TPtrC16 aModule ) +{ + CSerialTransport *self = new (ELeave) CSerialTransport(); + CleanupStack::PushL(self); + self->ConstructL( aModule ); + CleanupStack::Pop(); + return self; +} + +CSerialTransport::CSerialTransport() +{ +} + +CSerialTransport::~CSerialTransport() +{ + iCommPort.Close(); + iCommServer.Close(); +} + +void CSerialTransport::ConstructL( TPtrC16 aModule ) +{ + // set parameters + assert( aModule.Length() <= KModuleSize ); + iModule.Copy( aModule ); + iSerialStatus = EIdle; + iRetries = 0; + iCommPortOpen = 0; + iCommOldSettingsValid = 0; +} + +/************************************************************************************** + * + * CSerialTransport - Initialise and Release + * + *************************************************************************************/ +TInt CSerialTransport::InitialiseL() +{ + TInt r; + + // set the state + SetStatus( EInitialising ); + + // Under WINS we must force a link to the file server so that we're sure we'll be + // able to load the device drivers. On a MARM implementation, this code would not + // be required because higher level components (EIKON) will automatically have started + // the services. NOTE: this is now no longer required since we are an app and so even + // on WINS everything else should have started up by now. + + // Load up the physical and the logical device drivers. If they are already loaded + // then it won't make any difference. + r = User::LoadPhysicalDevice( PDD_NAME ); + if( (r != KErrNone) && (r != KErrAlreadyExists) ) { + User::Leave( r ); + } + r = User::LoadLogicalDevice( LDD_NAME ); + if( (r != KErrNone) && (r != KErrAlreadyExists) ) { + User::Leave( r ); + } + + // Both WINS and EIKON will have started the comms server process. + // (this is only really needed for ARM hardware development racks) +#ifndef __WINS__ + r = StartC32(); + if( (r != KErrNone) && (r != KErrAlreadyExists) ) + User::Leave( r ); +#endif + + // Now connect to the comm server + User::LeaveIfError( iCommServer.Connect() ); + + // Load the CSY module + r = iCommServer.LoadCommModule( iModule ); + User::LeaveIfError( r ); + + // check we loaded correctly + TInt numPorts; + r = iCommServer.NumPorts( numPorts ); + User::LeaveIfError( r ); + + // set the state + SetStatus( EInitialised ); + return KErrNone; +} + +TInt CSerialTransport::Release(void) +{ + // make sure the status is as expected + assert( (iSerialStatus == EInitialising) || (iSerialStatus == EInitialised) || (iSerialStatus == EDisconnected) ); + SetStatus( EReleasing ); + + // disconnect from the comms server + iCommServer.Close(); + + // update state and finish + SetStatus( EIdle ); + return KErrNone; +} + +/************************************************************************************** + * + * CSerialTransport - Connect and Close + * + *************************************************************************************/ +static int atoi( const short *str ) +{ + int ret = 0; + for( int i = 0; str[i] != NULL; i++ ) { + ret *= 10; + ret += str[i] - '0'; + } + return ret; +} + +void CSerialTransport::ExtractOptions( TDesC *aRemoteHost, TInt& aPortNumber, TInt& aBaudCap, TBps& aBaudRate ) +{ + TInt baud; + short *delim; + + // get the character array for the remote host (note that this is in unicode) + short *opt = (short*)aRemoteHost->Ptr(); + + // extract the portnumber + aPortNumber = opt[0] - '0'; + + // make sure the next char is a delimiter + assert( opt[1] == OPT_DELIMITER ); + + // now search for the next delimiter and NULL it + for( delim = &opt[2]; (*delim != NULL) && (*delim != OPT_DELIMITER); delim++ ) + ; + + // if this is a delim then NULL it + if( *delim == OPT_DELIMITER ) { + *delim = NULL; + } + + // extract the baud -- and set the correct constants for the given baud + baud = atoi( &(opt[2]) ); + switch( baud ) { + case 115200: + aBaudRate = EBps115200; + aBaudCap = KCapsBps115200; + break; + case 38400: + aBaudRate = EBps38400; + aBaudCap = KCapsBps38400; + break; + case 19200: + aBaudRate = EBps19200; + aBaudCap = KCapsBps19200; + break; + case 9600: + aBaudRate = EBps9600; + aBaudCap = KCapsBps9600; + break; + default: + assert( !"Unsupported baud rate" ); + break; + } +} + +TInt CSerialTransport::ConnectL( TDesC *aRemoteHost ) +{ + TInt portNumber; + TInt baudCap; + TBps baudRate; + + TBuf8<1> iDummyBuffer; + + // verify state + assert( iSerialStatus == EInitialised ); + SetStatus( EConnecting ); + + // extract the options from the string + ExtractOptions( aRemoteHost, portNumber, baudCap, baudRate ); + + // construct the address -- aRemoteHost should provide the COM port number + TBuf16 portName; + portName.Num( portNumber ); + portName.Insert( 0, _L("::") ); + if( iModule == _L("IrCOMM") ) + portName.Insert( 0, _L("IrCOMM") ); + else if( iModule == _L("ECUART") ) + portName.Insert( 0, _L("COMM") ); + + // open the serial port + TInt r = iCommPort.Open( iCommServer, portName, ECommExclusive ); + User::LeaveIfError( r ); + iCommPortOpen = 1; + + // check our configuration is supported + TCommCaps ourCapabilities; + iCommPort.Caps( ourCapabilities ); + if (((ourCapabilities ().iRate & baudCap) == 0) || + ((ourCapabilities ().iDataBits & KCapsData8) == 0) || + ((ourCapabilities ().iStopBits & KCapsStop1) == 0) || + ((ourCapabilities ().iParity & KCapsParityNone) == 0)) + { + User::Leave( KErrNotSupported ); + } + + + // save port settings for restoring later + iCommPort.Config( iOldPortSettings ); + iCommOldSettingsValid = 1; + + // set new port settings + iCommPort.Config( iPortSettings ); + iPortSettings().iRate = baudRate; + iPortSettings().iParity = EParityNone; + iPortSettings().iDataBits = EData8; + iPortSettings().iStopBits = EStop1; + iPortSettings().iFifo = EFifoEnable; + iPortSettings().iHandshake = KConfigObeyCTS; + iPortSettings().iTerminatorCount = 0; + + // cancel any pending reads / writes to be safe and set the config + iCommPort.Cancel(); + r = iCommPort.SetConfig( iPortSettings ); + if( r != KErrNone ) { + User::Leave(r); + } + + // set the receive buffer length then check it did it ok + iCommPort.SetReceiveBufferLength( 2*KMaxPacketSize ); + if( iCommPort.ReceiveBufferLength() != 2*KMaxPacketSize ) { + User::Leave( KErrTooBig ); + } + + // power up the serial port by doing a null read on the port + if( iModule != _L("IrCOMM") ) { + iCommPort.Read(iStatus, iDummyBuffer,0); + User::WaitForRequest(iStatus); + if(iStatus.Int() != KErrNone){ + Disconnect(); + Release(); + User::Leave(iStatus.Int()); + + } + } else { + iCommPort.Write(iStatus, iDummyBuffer,0); + User::WaitForRequest(iStatus); + if(iStatus.Int() != KErrNone){ + Disconnect(); + Release(); + User::Leave(iStatus.Int()); + + } + } + + SetStatus(EConnected); + return KErrNone; +} + +TInt CSerialTransport::Disconnect(void) +{ + // verify the status + assert( (iSerialStatus == EConnected) || (iSerialStatus == EConnecting) ); + SetStatus( EDisconnecting ); + + // clean up the port + if( iCommPortOpen ) + iCommPort.Cancel(); + if( iCommOldSettingsValid ) + iCommPort.SetConfig( iOldPortSettings ); + if( iCommPortOpen ) + iCommPort.Close(); + iCommPortOpen = 0; + iCommOldSettingsValid = 0; + + // done + SetStatus( EDisconnected ); + return KErrNone; +} + +/************************************************************************************** + * + * CSerialTransport - Receive and Send. The ID / Length / Data nonsense + * is handled by the packetisation layer. All serial has to do here is send data -- + * serial is also assuming that the upper layer will keep the data until the response + * + *************************************************************************************/ +TInt CSerialTransport::RequestSend( TDesC8 *aData, const TUint aDataLength ) +{ + + // make sure we are in the appropriate state + assert( iSerialStatus == EConnected ); + + // do the send + assert( (unsigned)aData->Length() == aDataLength ); + iCommPort.Write( iStatus, (*aData), aDataLength ); + User::WaitForRequest(iStatus); + return iStatus.Int(); +} + +TInt CSerialTransport::RequestReceive( TPtr8 *recvBufferPtr,TUint aByteCount ) +{ + // make sure we are in the appropriate state + assert( iSerialStatus == EConnected ); + + // allocate a buffer for the read + assert( aByteCount <= KMaxPacketSize ); + recvBufferPtr->SetLength( 0 ); + iCommPort.ReadCancel(); + iCommPort.Read( iStatus, *recvBufferPtr, aByteCount ); + User::WaitForRequest(iStatus); + return iStatus.Int(); +} + +TText8 *CSerialTransport::Error( void ) +{ + return NULL; +} + +/************************************************************************************** + * + * CSerialTransport - Private Functions + * + *************************************************************************************/ +void CSerialTransport::SetStatus( TCommStatus aNewStatus ) +{ + iSerialStatus = aNewStatus; +}