dbgagents/trkagent/engine/TrkSerialCommPort.cpp
author bdonegan
Thu, 30 Sep 2010 16:15:48 +0100
changeset 3 b667e5204120
parent 0 c6b0df440bee
permissions -rw-r--r--
Remove reference to cinidata in order to allow TrkEngine to build

/*
* Copyright (c) 2004 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 <f32file.h>

#include "TrkEngineModel.h"
#include "TrkSerialCommPort.h"
#include "TrkFramingLayer.h"


//
// 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 TUint RateCapacityBitMaskFromRate(TUint aRate)
{
	switch (aRate)
	{
		case 50:      return KCapsBps50;
		case 75:      return KCapsBps75;
		case 110:     return KCapsBps110;
		case 134:     return KCapsBps134;
		case 150:     return KCapsBps150;
		case 300:     return KCapsBps300;
		case 600:     return KCapsBps600;
		case 1200:    return KCapsBps1200;
		case 1800:    return KCapsBps1800;
		case 2000:    return KCapsBps2000;
		case 2400:    return KCapsBps2400;
		case 3600:    return KCapsBps3600;
		case 4800:    return KCapsBps4800;
		case 7200:    return KCapsBps7200;
		case 9600:    return KCapsBps9600;
		case 19200:   return KCapsBps19200;
		case 38400:   return KCapsBps38400;
		case 57600:   return KCapsBps57600;
		case 115200:  return KCapsBps115200;
		case 230400:  return KCapsBps230400;
		case 460800:  return KCapsBps460800;
		case 576000:  return KCapsBps576000;
		case 1152000: return KCapsBps1152000;
		case 4000000: return KCapsBps4000000;
		default:      return 0;
	}
}

static TBps TBpsRateFromRate(TUint aRate)
{
	switch (aRate)
	{
		case 50:      return EBps50;
		case 75:      return EBps75;
		case 110:     return EBps110;
		case 134:     return EBps134;
		case 150:     return EBps150;
		case 300:     return EBps300;
		case 600:     return EBps600;
		case 1200:    return EBps1200;
		case 1800:    return EBps1800;
		case 2000:    return EBps2000;
		case 2400:    return EBps2400;
		case 3600:    return EBps3600;
		case 4800:    return EBps4800;
		case 7200:    return EBps7200;
		case 9600:    return EBps9600;
		case 19200:   return EBps19200;
		case 38400:   return EBps38400;
		case 57600:   return EBps57600;
		case 115200:  return EBps115200;
		case 230400:  return EBps230400;
		case 460800:  return EBps460800;
		case 576000:  return EBps576000;
		case 1152000: return EBps1152000;
		case 4000000: return EBps4000000;
		default:      return EBpsAutobaud;
	}
}


//
//
// CTrkSerialCommPort implementation
//
//

//
// CTrkSerialCommPort constructor
//
CTrkSerialCommPort::CTrkSerialCommPort()
	: CTrkCommPort(CActive::EPriorityStandard),
	  iPDD(NULL),
	  iPDD2(NULL),
	  iLDD(NULL),
	  iCSY(NULL),
	  iServerStarted(EFalse),
	  iConnected(EFalse),
	  iListening(EFalse),
	  iLineNumber(0)
{
}

//
// CTrkSerialCommPort::ConstructL
//
void CTrkSerialCommPort::ConstructL(TTrkConnData& aTrkConnData , TDes& aErrorMessage)
{
	iPDD = aTrkConnData.iPDD;
	iLDD = aTrkConnData.iLDD;
	iCSY = aTrkConnData.iCSY;
	iUnitNumber = aTrkConnData.iPortNumber;
	iRate = aTrkConnData.iRate;
	
	
	TBuf<KMaxPath> initFile(KInitFilePath);
	initFile.Append(KInitFileName);
	
	if (!iPDD.Size())
	{
		aErrorMessage.Format(_L("PDD not specified in %S.\r\n"), &initFile);
			User::Leave(KErrCorrupt);
		}

	if (!iLDD.Size())
	{
		aErrorMessage.Format(_L("LDD not specified in %S.\r\n"), &initFile);		
			User::Leave(KErrCorrupt);
		}

	if (!iCSY.Size())
	{
		aErrorMessage.Format(_L("CSY not specified in %S.\r\n"), &initFile);		
			User::Leave(KErrCorrupt);
		}

		if (!iRate)
		{
		aErrorMessage.Format(_L("RATE not specified in %S.\r\n"), &initFile);		
			User::Leave(KErrCorrupt);
		}
	
	iPDD2.Format(iPDD, iUnitNumber+1);
		
	iConnectionMessage.Format(_L("PDD: %S\r\nLDD: %S\r\nCSY: %S\r\nPort number: %d\r\nBaud rate: %d\r\n"), &iPDD2, &iLDD, &iCSY, iUnitNumber, iRate);

	if (aTrkConnData.iDefault)
	{
		iConnectionMessage.Insert(0, _L("No init file found, using default values.\r\n"));
	}
}

//
// CTrkSerialCommPort destructor
//
CTrkSerialCommPort::~CTrkSerialCommPort()
{
	// make sure we cancel the request for data before shutting down
	Cancel();

	iPort.Close();
	iConnected = EFalse;
	iServer.Close();
	iServerStarted = EFalse;	
}

//
// CTrkSerialCommPort::NewL
//
CTrkSerialCommPort* CTrkSerialCommPort::NewL(TTrkConnData& aTrkConnData, TDes& aErrorMessage)
{
	CTrkSerialCommPort* self = new(ELeave) CTrkSerialCommPort;
	CleanupStack::PushL(self);
	self->ConstructL(aTrkConnData, aErrorMessage);
	CleanupStack::Pop(self);
	return self;
}

//
// CTrkSerialCommPort::OpenPortL
//
// Open the serial type communications port
//
void CTrkSerialCommPort::OpenPortL()
{
	TInt error = KErrNone;

	if (!iServerStarted)
	{
		StartC32();
		ReportAndLeaveIfErrorL(iServer.Connect(),
							  _L("Failed to connect to RCommServ."));
		iServerStarted = ETrue;
	}

	// load the csy module
	ReportAndLeaveIfErrorL(iServer.LoadCommModule(iCSY), _L("Failed to load CSY module."));

	TInt ports = 0;
	ReportAndLeaveIfErrorL(iServer.NumPorts(ports),
						   _L("Unable to obtain information about port."));

	// 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;
		ReportAndLeaveIfErrorL(iServer.GetPortInfo(i, module, serialInfo),
							   _L("Unable to obtain information about port."));		
		module.LowerCase();
		if (module == csyModule)
			error = KErrNone;
	}

	ReportAndLeaveIfErrorL(error, _L("Unable to obtain port information for comm module."));
	
	//If pdd is "NONE", don't try to load it.
	//This is true incase of USB, where the USB pdd is a kernel extension on most of the phones
	//and so can't be loaded.
	TBuf<10> defaultUsbPdd;
	defaultUsbPdd.Copy(KDefaultUsbPDD);	
	if (iPDD2.Compare(defaultUsbPdd))
	{
		error = User::LoadPhysicalDevice(iPDD2);
		if (error != KErrNone && error != KErrAlreadyExists)
			ReportAndLeaveIfErrorL(error, _L("Failed to load physical device."));
	}

	error = User::LoadLogicalDevice(iLDD);
	if (error != KErrNone && error != KErrAlreadyExists)
		ReportAndLeaveIfErrorL(error, _L("Failed to load logical device."));

	// Open port (try first in DTE mode and then if unsuccessful in
	// DCE mode - necessary for cogent).

	TBuf<KMaxPortName+4> portName;
	BuildPortName(serialInfo.iName, iUnitNumber, portName);
	error = iPort.Open(iServer, portName, ECommExclusive, ECommRoleDTE);
	if (error != KErrNone)
	{
		ReportAndLeaveIfErrorL(iPort.Open(iServer, portName, ECommExclusive, ECommRoleDCE),
							   _L("Failed to open port."));
	}
	iConnected = ETrue;

	// Check Speed
	TCommCaps caps;
	iPort.Caps(caps);

	TUint rateBitMask = RateCapacityBitMaskFromRate(iRate);
	if (rateBitMask == 0 || (rateBitMask & caps().iRate) == 0)
		ReportAndLeaveIfErrorL(KErrGeneral, _L("Unsupported baud rate."));

	// Configure physical and logical characteristics
	TCommConfig config;
	iPort.Config(config);
	config().iRate = TBpsRateFromRate(iRate);
	config().iParity = EParityNone;
	config().iDataBits = EData8;
	config().iStopBits = EStop1;
	config().iFifo = EFifoEnable;

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

	ReportAndLeaveIfErrorL(iPort.SetConfig(config), _L("Failed to set port configuration."));

	iPort.SetReceiveBufferLength(MAXMESSAGESIZE);

	//reset the rx and tx buffers just in case 
	//if there is any stale data lying around from the previous debug sessions
	iPort.ResetBuffers(); 
}

//
// CTrkSerialCommPort::ClosePort
//
// Close the communications port
//
void CTrkSerialCommPort::ClosePort()
{
	Cancel();
	
	if (iConnected)
	{
		iPort.Close();
		iConnected = EFalse;
	}

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

//
// CTrkSerialCommPort::SendDataL
//
// Write data to the serial type port
//
void CTrkSerialCommPort::SendDataL(const TDesC8& aBuffer)
{
	//_LIT8(KPrefix, "TrkToCarbide: ");
	//PrintMessage(KPrefix(), aBuffer);
	
	TRequestStatus status;
	iPort.Write(status, aBuffer);
	User::WaitForRequest(status);
	
	User::LeaveIfError(status.Int());
}

//
// CTrkSerialCommPort::Listen
//
// Start listening for data coming into the serial type communications port
//
void CTrkSerialCommPort::Listen(CTrkFramingLayer *aFramingLayer)
{
	iFramingLayer = aFramingLayer;
	CActiveScheduler::Add(this);
	IssueReadRequest();
	iListening = ETrue;
}

//
// CTrkSerialCommPort::StopListening
//
// Stop listening for data coming into the serial type communications port
//
void CTrkSerialCommPort::StopListening()
{
	if (iListening)
	{
		Cancel();
		Deque();
	}
	
	iListening = EFalse;
}

//
// CTrkSerialCommPort::ReportAndLeaveIfErrorL
//
// If an error occurred, print the error information to the screen and bail out
//
void CTrkSerialCommPort::ReportAndLeaveIfErrorL(TInt aError, const TDesC& aDesc)
{
	if (KErrNone != aError)
	{
		iErrorMessage.Format(_L("%S\r\nError Code: %d\r\n"), &aDesc, aError);
		User::Leave(aError);
	}
}

//
// CTrkSerialCommPort::IssueReadRequest
//
// Wait for data to come into the communications port
//
void CTrkSerialCommPort::IssueReadRequest()
{
	iNextReadChar = 0;
	iReceivedChars.Zero();
	iPort.ReadOneOrMore(iStatus, iReceivedChars);

	SetActive();
}

//
// CTrkSerialCommPort::DoCancel
//
// Cancel the request for data from the communications port
//
void CTrkSerialCommPort::DoCancel()
{
	iPort.ReadCancel();
}

//
// CTrkSerialCommPort::RunL
//
// Called when data comes into the communications port
//
void CTrkSerialCommPort::RunL()
{
	//_LIT8(KPrefix, "CarbideToTrk: ");
	//PrintMessage(KPrefix(), iReceivedChars);

	// pass the data onto the framing layer
	if (iStatus.Int() == KErrNone)
		while (iNextReadChar < iReceivedChars.Length())
			iFramingLayer->HandleByte(iReceivedChars[iNextReadChar++]);

	// continue waiting for data
	IssueReadRequest();
}

void CTrkSerialCommPort::PrintMessage(const TDesC8& aPrefix, const TDesC8& aBinaryData) const
	{
	TInt msgLength = aBinaryData.Length();
	//RDebug::Printf("%S - start", &aPrefix);
	for(TInt i=0; i<msgLength; i+=8)
		{
		TBuf8<30> tempBuf;
		tempBuf.SetLength(0);
		for(TInt j=i; (j<i+8) && (j<msgLength); j++)
			{
			TUint byte = (TUint)aBinaryData[j];
			tempBuf.AppendNumFixedWidth(byte, EHex, 2);
			tempBuf.Append(' ');
			}
		//RDebug::Printf("%S: [%S]", &aPrefix, &tempBuf);
		}
	//RDebug::Printf("%S - end", &aPrefix);

	}