dbgagents/trkagent/dbgtrccomm/server/dbgtrcportmgr.cpp
author ravikurupati
Tue, 02 Mar 2010 10:33:16 +0530
changeset 0 c6b0df440bee
permissions -rw-r--r--
Initial contribution of EPL licensed sources

/*
* Copyright (c) 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: 
*
*/


#include <e32cons.h>
#include <e32base.h>

#include "logging.h"
#include "portreader.h"
#include "portwriter.h"
#include "dbgtrcportmgr.h"

//default USB settings
_LIT(KDefaultUsbPDD, "NONE");
_LIT(KDefaultUsbLDD, "EUSBC");
_LIT(KDefaultUsbCSY, "ECACM");
#define KDefaultUsbPort 1

// uncomment the line below for testing with serial port on H4 or H2 board
//#define SERIAL

//
// Static helper functions
//
static void BuildPortName(const TDesC& aModuleName, TUint aUnit, TDes& aCompleteName)
{
	aCompleteName.Zero();
	aCompleteName.Append(aModuleName);
	aCompleteName.AppendFill(':', 2);
	aCompleteName.AppendNum(aUnit);
}

static TBps TBpsRateFromDbgTrcBaudRate(TBaudRates aRate)
{
	switch (aRate)
	{
		case EBaud50:      return EBps50;
		case EBaud75:      return EBps75;
		case EBaud110:     return EBps110;
		case EBaud134:     return EBps134;
		case EBaud150:     return EBps150;
		case EBaud300:     return EBps300;
		case EBaud600:     return EBps600;
		case EBaud1200:    return EBps1200;
		case EBaud1800:    return EBps1800;
		case EBaud2000:    return EBps2000;
		case EBaud2400:    return EBps2400;
		case EBaud3600:    return EBps3600;
		case EBaud4800:    return EBps4800;
		case EBaud7200:    return EBps7200;
		case EBaud9600:    return EBps9600;
		case EBaud19200:   return EBps19200;
		case EBaud38400:   return EBps38400;
		case EBaud57600:   return EBps57600;
		case EBaud115200:  return EBps115200;
		case EBaud230400:  return EBps230400;
		case EBaud460800:  return EBps460800;
		case EBaud576000:  return EBps576000;
		case EBaud1152000: return EBps1152000;
		case EBaud4000000: return EBps4000000;
		default:  		   return EBpsAutobaud;
	}
}


CDbgTrcPortMgr*	CDbgTrcPortMgr::NewL()
{
	LOG_MSG("CDbgTrcPortMgr::NewL");

	CDbgTrcPortMgr* self = new(ELeave) CDbgTrcPortMgr;
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
}

CDbgTrcPortMgr::~CDbgTrcPortMgr()
{
	LOG_MSG("CDbgTrcPortMgr::~CDbgTrcPortMgr");

	SafeDelete(iReader);
	SafeDelete(iWriter);
}

void CDbgTrcPortMgr::ConstructL()
{
	LOG_MSG("CDbgTrcPortMgr::ConstructL");

	iReader = NULL;
	iWriter = NULL;
	
#ifdef SERIAL // for testing with serial on H4 or H2 board.
	iPDD.Copy(_L("EUART1"));
	iLDD.Copy(_L("ECOMM"));
	iCSY.Copy(_L("ECUART"));
	iPortNumber = 3;
#else
	//set the default ACM port settings.	
	iPDD.Copy(KDefaultUsbPDD);
	iLDD.Copy(KDefaultUsbLDD);
	iCSY.Copy(KDefaultUsbCSY);
	iPortNumber = KDefaultUsbPort;	
#endif

	iRate = EBaud115200;
	
	iConnected = EFalse;
	iActiveConnections = 0;
	iServerStarted = EFalse;
	
	iAcmConfig.iBaudRate = iRate;
	iAcmConfig.iPortNumber = iPortNumber;
}

void CDbgTrcPortMgr::GetPortConfig(TDes8& aDes)
{
	LOG_MSG("CDbgTrcPortMgr::GetPortConfig");

	TPtrC8 cfg((const TUint8*)&iAcmConfig, sizeof(iAcmConfig));
	aDes.Copy(cfg);	
}

TInt CDbgTrcPortMgr::SetPortConfig(const TDesC8& aDes)
{
	LOG_MSG("CDbgTrcPortMgr::SetPortConfig");

	if (iConnected)
		return KErrInUse;
		
	if (aDes.Length()<(TInt)sizeof(TAcmConfigV01))
		return KErrGeneral;
	TAcmConfigV01 config(*(TAcmConfigV01*)aDes.Ptr());
	
	iPortNumber = config.iPortNumber;
	iRate = config.iBaudRate;
	
	iAcmConfig.iBaudRate = iRate;
	iAcmConfig.iPortNumber = iPortNumber;
	
	return KErrNone;
}


//
// CDbgTrcPortMgr::OpenPortL
//
// Open the ACM port
//
TInt CDbgTrcPortMgr::OpenPortL()
{
	LOG_MSG("CDbgTrcPortMgr::OpenPort");

	TInt error = KErrNone;
	
	if (iConnected)
	{
		iActiveConnections++;
		return error; //return KErrNone if the connection is already opened by another client.
	}

	if (!iServerStarted)
	{
		StartC32();
		error = iServer.Connect();
		if (error == KErrNone)
		{
			iServerStarted = ETrue;
			LOG_MSG("C32 Server started");
		}
	}											  
		
	if (iServerStarted)
	{
		error = iServer.LoadCommModule(iCSY);
		if (error == KErrNone)
		{
			LOG_MSG("CSY Loaded:");

			TInt ports = 0;
			error = iServer.NumPorts(ports);
			
			if (error == KErrNone)
			{
				LOG_MSG2("Number of ports: %d", ports);

				// make sure the unit number is in range
				TSerialInfo serialInfo;

				error = KErrNotFound;
				
				TBuf<32> csyModule;
				csyModule = iCSY;
				csyModule.LowerCase();
				for (TInt i=0; i<ports && error; i++)
				{
					TBuf<32> module;
					TInt err1 = iServer.GetPortInfo(i, module, serialInfo);
					
					// come out of the loop and error out if we are not able
					// to get the port info.
					if (err1 != KErrNone) 
						break;
										   
					module.LowerCase();
					LOG_MSG("Module name: ");

					if (!module.Compare(csyModule))
					{
						error = KErrNone;
						LOG_MSG("CSY Module matched");
					}
				}
				
				if (error == KErrNone)
				{		
					LOG_MSG("CSY Module found");			
					if (iPDD.Compare(KDefaultUsbPDD))
						error = User::LoadPhysicalDevice(iPDD);
					
					if (error == KErrNone || error == KErrAlreadyExists)
					{
						error = User::LoadLogicalDevice(iLDD);
						if (error == KErrNone || error == KErrAlreadyExists)
						{
							error = KErrNone;
							TBuf<KMaxPortName+4> portName;
							BuildPortName(serialInfo.iName, iPortNumber, portName);
							
							error = iPort.Open(iServer, portName, ECommExclusive, ECommRoleDTE);
							if (error != KErrNone)
							{
								LOG_MSG("Unable to open port in DTE mode");
								
								error = iPort.Open(iServer, portName, ECommExclusive, ECommRoleDCE);												  
							}
							
							if (error == KErrNone)
							{
								LOG_MSG("Port opened");
								
								// Configure physical and logical characteristics
								TCommConfig config;
								iPort.Config(config);
								config().iRate = TBpsRateFromDbgTrcBaudRate(iRate);
								config().iParity = EParityNone;
								config().iDataBits = EData8;
								config().iStopBits = EStop1;
								config().iFifo = EFifoEnable;

								config().iHandshake = 0;	// no flow control at all

								error = iPort.SetConfig(config);
								
								if (error == KErrNone)
								{
									LOG_MSG("Port configuration set");

									//iPort.SetReceiveBufferLength(MAX_BUF_SIZE);									
									iConnected = ETrue;
									//reset the rx and tx buffers just in case 
									//if there is any stale data lying around from the previous debug sessions
									iPort.ResetBuffers(); 
									
									// now increment the active connections counter
									iActiveConnections++;
									
									// now create the port reader and writer.
									iReader = CPortReader::NewL(iPort);
									iWriter = CPortWriter::NewL(iPort);																
								}							
							}
						}
					}
				}
			}
		}
	}
	
	if (iServerStarted && !iConnected)  
	{
		iServer.Close();
		iServerStarted = EFalse;
	}	

	return error;
}


//
// CDbgTrcPortMgr::ClosePort
//
// Close the ACM port
//
TInt CDbgTrcPortMgr::ClosePort()
{	
	// now decrement the active connections counter
	if (iActiveConnections > 0)	
		iActiveConnections--; 

	if (iActiveConnections == 0) // close the actual port only when the number of active connections is 0
	{
		SafeDelete(iReader);
		SafeDelete(iWriter);

		if (iConnected)
		{
			iPort.Close();
			iConnected = EFalse;
		}

		if (iServerStarted)
		{
			iServer.Close();
			iServerStarted = EFalse;
		}		
	}
	
	return KErrNone;
}

//
// CDbgTrcPortMgr::GetPortReader
//
//
CPortReader* CDbgTrcPortMgr::GetPortReader()
{
	if (iConnected)
		return iReader;
	
	return NULL;
}

//
// CDbgTrcPortMgr::GetPortReader
//
//
CPortWriter* CDbgTrcPortMgr::GetPortWriter()
{
	if (iConnected)
		return iWriter;
	
	return NULL;
}