dbgagents/trkagent/engine/TrkSerialCommPort.cpp
changeset 0 c6b0df440bee
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbgagents/trkagent/engine/TrkSerialCommPort.cpp	Tue Mar 02 10:33:16 2010 +0530
@@ -0,0 +1,444 @@
+/*
+* 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);
+
+	}