testexecmgmt/ucc/Source/UCCSDeviceControl/CSerialTransport.cpp
changeset 0 3da2a79470a7
--- /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<KMaxPortName + 4> 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;
+}