testexecmgmt/ucc/Source/UCCSDeviceControl/CSerialTransport.cpp
changeset 0 3da2a79470a7
equal deleted inserted replaced
-1:000000000000 0:3da2a79470a7
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 * Local Includes
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include "assert.h"
       
    22 #include "CSerialTransport.h"
       
    23 
       
    24 /**************************************************************************************
       
    25  *
       
    26  * Definitions
       
    27  *
       
    28  *************************************************************************************/
       
    29 _LIT(LDD_NAME,"ECOMM");
       
    30 #ifdef __WINS__
       
    31 _LIT(PDD_NAME,"ECDRV");
       
    32 #else
       
    33 _LIT(PDD_NAME,"EUART1");
       
    34 #endif
       
    35 
       
    36 #define KMaxTimeoutRetries	(0x0FFFFFFF)
       
    37 #define KWriteTimeout		50000000
       
    38 
       
    39 /********************************************************************************
       
    40  *
       
    41  * Macro functions
       
    42  *
       
    43  ********************************************************************************/
       
    44 
       
    45 /**************************************************************************************
       
    46  *
       
    47  * CSerialTransport - Construction
       
    48  *
       
    49  *************************************************************************************/
       
    50 CSerialTransport* CSerialTransport::NewL( TPtrC16 aModule )
       
    51 {
       
    52     CSerialTransport *self = new (ELeave) CSerialTransport();
       
    53     CleanupStack::PushL(self);
       
    54 	self->ConstructL( aModule );
       
    55 	CleanupStack::Pop();
       
    56     return self;
       
    57 }
       
    58 
       
    59 CSerialTransport::CSerialTransport() 
       
    60 {
       
    61 }
       
    62 
       
    63 CSerialTransport::~CSerialTransport()
       
    64 {
       
    65 	iCommPort.Close();
       
    66 	iCommServer.Close();
       
    67 }
       
    68 
       
    69 void CSerialTransport::ConstructL( TPtrC16 aModule )
       
    70 {
       
    71 	// set parameters
       
    72 	assert( aModule.Length() <= KModuleSize );
       
    73 	iModule.Copy( aModule );
       
    74 	iSerialStatus = EIdle;
       
    75 	iRetries = 0;
       
    76 	iCommPortOpen = 0;
       
    77 	iCommOldSettingsValid = 0;
       
    78 }
       
    79 
       
    80 /**************************************************************************************
       
    81  *
       
    82  * CSerialTransport - Initialise and Release
       
    83  *
       
    84  *************************************************************************************/
       
    85 TInt CSerialTransport::InitialiseL()
       
    86 {
       
    87 	TInt r;
       
    88 
       
    89 	// set the state
       
    90 	SetStatus( EInitialising );
       
    91 
       
    92 	// Under WINS we must force a link to the file server so that we're sure we'll be 
       
    93 	// able to load the device drivers. On a MARM implementation, this code would not
       
    94 	// be required because higher level components (EIKON) will automatically have started 
       
    95 	// the services. NOTE: this is now no longer required since we are an app and so even
       
    96 	// on WINS everything else should have started up by now.
       
    97 
       
    98 	// Load up the physical and the logical device drivers. If they are already loaded 
       
    99 	// then it won't make any difference.
       
   100 	r = User::LoadPhysicalDevice( PDD_NAME );
       
   101 	if( (r != KErrNone) && (r != KErrAlreadyExists) ) {
       
   102 		User::Leave( r );
       
   103 	}
       
   104 	r = User::LoadLogicalDevice( LDD_NAME );	
       
   105 	if( (r != KErrNone) && (r != KErrAlreadyExists) ) {
       
   106 		User::Leave( r );
       
   107 	}
       
   108 
       
   109 	// Both WINS and EIKON will have started the comms server process.
       
   110 	// (this is only really needed for ARM hardware development racks)
       
   111 #ifndef __WINS__
       
   112 	r = StartC32();
       
   113 	if( (r != KErrNone) && (r != KErrAlreadyExists) )
       
   114 		User::Leave( r );
       
   115 #endif
       
   116 
       
   117 	// Now connect to the comm server	
       
   118 	User::LeaveIfError( iCommServer.Connect() );
       
   119 
       
   120 	// Load the CSY module
       
   121 	r = iCommServer.LoadCommModule( iModule );
       
   122 	User::LeaveIfError( r );
       
   123 
       
   124 	// check we loaded correctly
       
   125 	TInt numPorts;
       
   126 	r = iCommServer.NumPorts( numPorts );
       
   127 	User::LeaveIfError( r );
       
   128 
       
   129 	// set the state
       
   130 	SetStatus( EInitialised );
       
   131 	return KErrNone;
       
   132 }
       
   133 
       
   134 TInt CSerialTransport::Release(void)
       
   135 {
       
   136 	// make sure the status is as expected
       
   137 	assert( (iSerialStatus == EInitialising) || (iSerialStatus == EInitialised) || (iSerialStatus == EDisconnected) );
       
   138 	SetStatus( EReleasing );
       
   139 
       
   140 	// disconnect from the comms server
       
   141 	iCommServer.Close();
       
   142 
       
   143 	// update state and finish
       
   144 	SetStatus( EIdle );
       
   145 	return KErrNone;
       
   146 }
       
   147 
       
   148 /**************************************************************************************
       
   149  *
       
   150  * CSerialTransport - Connect and Close
       
   151  *
       
   152  *************************************************************************************/
       
   153 static int atoi( const short *str )
       
   154 {
       
   155 	int ret = 0;
       
   156 	for( int i = 0; str[i] != NULL; i++ ) {
       
   157 		ret *= 10;
       
   158 		ret += str[i] - '0';
       
   159 	}
       
   160 	return ret;
       
   161 }
       
   162 
       
   163 void CSerialTransport::ExtractOptions( TDesC *aRemoteHost, TInt& aPortNumber, TInt& aBaudCap, TBps& aBaudRate )
       
   164 {
       
   165 	TInt baud;
       
   166 	short *delim;
       
   167 
       
   168 	// get the character array for the remote host (note that this is in unicode)
       
   169 	short *opt = (short*)aRemoteHost->Ptr();
       
   170 
       
   171 	// extract the portnumber
       
   172 	aPortNumber = opt[0] - '0';
       
   173 
       
   174 	// make sure the next char is a delimiter
       
   175 	assert( opt[1] == OPT_DELIMITER );
       
   176 
       
   177 	// now search for the next delimiter and NULL it
       
   178 	for( delim = &opt[2]; (*delim != NULL) && (*delim != OPT_DELIMITER); delim++ )
       
   179 		;
       
   180 
       
   181 	// if this is a delim then NULL it
       
   182 	if( *delim == OPT_DELIMITER ) {
       
   183 		*delim = NULL;
       
   184 	}
       
   185 
       
   186 	// extract the baud -- and set the correct constants for the given baud
       
   187 	baud = atoi( &(opt[2]) ); 
       
   188 	switch( baud ) {
       
   189 	case 115200:
       
   190 		aBaudRate = EBps115200;
       
   191 		aBaudCap = KCapsBps115200;
       
   192 		break;
       
   193 	case 38400:
       
   194 		aBaudRate = EBps38400;
       
   195 		aBaudCap = KCapsBps38400;
       
   196 		break;
       
   197 	case 19200:
       
   198 		aBaudRate = EBps19200;
       
   199 		aBaudCap = KCapsBps19200;
       
   200 		break;
       
   201 	case 9600:
       
   202 		aBaudRate = EBps9600;
       
   203 		aBaudCap = KCapsBps9600;
       
   204 		break;
       
   205 	default:
       
   206 		assert( !"Unsupported baud rate" );
       
   207 		break;
       
   208 	}
       
   209 }
       
   210 
       
   211 TInt CSerialTransport::ConnectL( TDesC *aRemoteHost )
       
   212 {
       
   213 	TInt portNumber;
       
   214 	TInt baudCap;
       
   215 	TBps baudRate;
       
   216 
       
   217 	TBuf8<1> iDummyBuffer;
       
   218 	
       
   219 	// verify state 
       
   220 	assert( iSerialStatus == EInitialised );
       
   221 	SetStatus( EConnecting );
       
   222 
       
   223 	// extract the options from the string
       
   224 	ExtractOptions( aRemoteHost, portNumber, baudCap, baudRate ); 
       
   225 
       
   226 	// construct the address -- aRemoteHost should provide the COM port number
       
   227 	TBuf16<KMaxPortName + 4> portName;
       
   228 	portName.Num( portNumber );
       
   229 	portName.Insert( 0, _L("::") );
       
   230 	if( iModule == _L("IrCOMM") ) 
       
   231 		portName.Insert( 0, _L("IrCOMM") );
       
   232 	else if( iModule == _L("ECUART") )
       
   233 		portName.Insert( 0, _L("COMM") );
       
   234 
       
   235 	// open the serial port
       
   236 	TInt r = iCommPort.Open( iCommServer, portName, ECommExclusive );
       
   237 	User::LeaveIfError( r );
       
   238 	iCommPortOpen = 1;
       
   239 
       
   240 	// check our configuration is supported
       
   241 	TCommCaps ourCapabilities;
       
   242 	iCommPort.Caps( ourCapabilities );
       
   243 	if (((ourCapabilities ().iRate & baudCap) == 0) ||
       
   244 		 ((ourCapabilities ().iDataBits & KCapsData8) == 0) ||
       
   245 		 ((ourCapabilities ().iStopBits & KCapsStop1) == 0) ||
       
   246 		 ((ourCapabilities ().iParity & KCapsParityNone) == 0)) 
       
   247 	{
       
   248 			User::Leave( KErrNotSupported );
       
   249 	}
       
   250 
       
   251 
       
   252 	// save port settings for restoring later
       
   253 	iCommPort.Config( iOldPortSettings );
       
   254 	iCommOldSettingsValid = 1;
       
   255 
       
   256 	// set new port settings
       
   257 	iCommPort.Config( iPortSettings );
       
   258 	iPortSettings().iRate = baudRate;
       
   259 	iPortSettings().iParity = EParityNone;
       
   260 	iPortSettings().iDataBits = EData8;
       
   261 	iPortSettings().iStopBits = EStop1;
       
   262 	iPortSettings().iFifo = EFifoEnable;
       
   263   	iPortSettings().iHandshake = KConfigObeyCTS;
       
   264 	iPortSettings().iTerminatorCount = 0;
       
   265 
       
   266 	// cancel any pending reads / writes to be safe and set the config
       
   267 	iCommPort.Cancel();
       
   268 	r = iCommPort.SetConfig( iPortSettings );
       
   269 	if( r != KErrNone ) {
       
   270 		User::Leave(r);
       
   271 	}
       
   272 
       
   273 	// set the receive buffer length then check it did it ok
       
   274 	iCommPort.SetReceiveBufferLength( 2*KMaxPacketSize );
       
   275 	if( iCommPort.ReceiveBufferLength() != 2*KMaxPacketSize ) {
       
   276 		User::Leave( KErrTooBig );
       
   277 	}
       
   278 
       
   279 	// power up the serial port by doing a null read on the port
       
   280 	if( iModule != _L("IrCOMM") ) {
       
   281 		iCommPort.Read(iStatus, iDummyBuffer,0);
       
   282 		User::WaitForRequest(iStatus);
       
   283 		if(iStatus.Int() != KErrNone){
       
   284 			Disconnect();
       
   285 			Release();
       
   286 			User::Leave(iStatus.Int());
       
   287 
       
   288 		}
       
   289 	} else {
       
   290 		iCommPort.Write(iStatus, iDummyBuffer,0);
       
   291 		User::WaitForRequest(iStatus);
       
   292 		if(iStatus.Int() != KErrNone){
       
   293 			Disconnect();
       
   294 			Release();
       
   295 			User::Leave(iStatus.Int());
       
   296 		
       
   297 		}
       
   298 	}
       
   299 
       
   300 	SetStatus(EConnected);
       
   301 	return KErrNone;
       
   302 }
       
   303 
       
   304 TInt CSerialTransport::Disconnect(void)
       
   305 {
       
   306 	// verify the status
       
   307 	assert( (iSerialStatus == EConnected) || (iSerialStatus == EConnecting) );
       
   308 	SetStatus( EDisconnecting );
       
   309 
       
   310 	// clean up the port
       
   311 	if( iCommPortOpen )
       
   312 		iCommPort.Cancel();
       
   313 	if( iCommOldSettingsValid )
       
   314 		iCommPort.SetConfig( iOldPortSettings );
       
   315 	if( iCommPortOpen )
       
   316 		iCommPort.Close();
       
   317 	iCommPortOpen = 0;
       
   318 	iCommOldSettingsValid = 0;
       
   319 
       
   320 	// done
       
   321 	SetStatus( EDisconnected );
       
   322 	return KErrNone;
       
   323 }
       
   324 
       
   325 /**************************************************************************************
       
   326  *
       
   327  * CSerialTransport - Receive and Send. The ID / Length / Data nonsense 
       
   328  * is handled by the packetisation layer. All serial has to do here is send data -- 
       
   329  * serial is also assuming that the upper layer will keep the data until the response
       
   330  *
       
   331  *************************************************************************************/
       
   332 TInt CSerialTransport::RequestSend( TDesC8 *aData, const TUint aDataLength )
       
   333 {
       
   334 
       
   335 	// make sure we are in the appropriate state 
       
   336 	assert( iSerialStatus == EConnected );
       
   337 
       
   338 	// do the send
       
   339 	assert( (unsigned)aData->Length() == aDataLength );
       
   340 	iCommPort.Write( iStatus, (*aData), aDataLength );
       
   341 	User::WaitForRequest(iStatus);
       
   342 	return iStatus.Int();
       
   343 }
       
   344 
       
   345 TInt CSerialTransport::RequestReceive( TPtr8 *recvBufferPtr,TUint aByteCount  )
       
   346 {
       
   347 	// make sure we are in the appropriate state
       
   348 	assert( iSerialStatus == EConnected );
       
   349 
       
   350 	// allocate a buffer for the read
       
   351 	assert( aByteCount <= KMaxPacketSize );
       
   352 	recvBufferPtr->SetLength( 0 );
       
   353 	iCommPort.ReadCancel();
       
   354 	iCommPort.Read( iStatus, *recvBufferPtr, aByteCount );
       
   355 	User::WaitForRequest(iStatus);
       
   356 	return iStatus.Int();
       
   357 }
       
   358 
       
   359 TText8 *CSerialTransport::Error( void )
       
   360 {
       
   361 	return NULL;
       
   362 }
       
   363 
       
   364 /**************************************************************************************
       
   365  *
       
   366  * CSerialTransport - Private Functions
       
   367  *
       
   368  *************************************************************************************/
       
   369 void CSerialTransport::SetStatus( TCommStatus aNewStatus )
       
   370 {
       
   371 	iSerialStatus = aNewStatus;
       
   372 }