dbgagents/trkagent/dbgtrccomm/server/ostbaserouter.cpp
changeset 0 c6b0df440bee
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbgagents/trkagent/dbgtrccomm/server/ostbaserouter.cpp	Tue Mar 02 10:33:16 2010 +0530
@@ -0,0 +1,519 @@
+/*
+* 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 <e32debug.h>
+#include <e32base.h>
+#include <e32cons.h>
+
+#include "logging.h"
+#include "dbgtrcportmgr.h"
+#include "ostprotregistry.h"
+#include "portreader.h"
+#include "portwriter.h"
+#include "dbgtrcsrvsession.h"
+#include "ostmessage.h"
+#include "ostbaserouter.h"
+
+// Static functions
+
+//
+// Swap2
+//
+// Byte-swaps a 2-byte value.  Used to convert to/from little/big endian.
+//
+static TUint16 Swap2(TUint16 aSource)
+{
+	TUint16 dest = 0;
+	for (TInt i=0; i<2; i++)
+	{
+		dest <<= 8;
+		dest |= aSource & 0xFF;
+		aSource >>= 8;
+	}
+	
+	return dest;
+} 
+
+COstWriteMsgEntry* COstWriteMsgEntry::NewL(TDesC8& aMsg, CDbgTrcSrvSession* aMsgListener)
+{
+	LOG_MSG("COstWriteMsgEntry::NewL");
+
+	COstWriteMsgEntry* self = new(ELeave) COstWriteMsgEntry(aMsgListener);
+	CleanupStack::PushL(self);
+	self->ConstructL(aMsg);
+	CleanupStack::Pop(self);
+	return self;
+}
+
+COstWriteMsgEntry::COstWriteMsgEntry(CDbgTrcSrvSession* aMsgListener)
+: iMessage(NULL),
+  iWriteMsgListener(aMsgListener)
+{
+	LOG_MSG("COstWriteMsgEntry::COstWriteMsgEntry");
+
+
+}
+
+COstWriteMsgEntry::~COstWriteMsgEntry()
+{
+	LOG_MSG("COstWriteMsgEntry::~COstWriteMsgEntry");
+
+	SafeDelete(iMessage);
+	iWriteMsgListener = NULL; //don't delete the listener since we don't really own it.
+}
+
+void COstWriteMsgEntry::ConstructL(TDesC8& aMsg)
+{
+	LOG_MSG("COstWriteMsgEntry::ConstructL");
+
+	iMessage = COstMessage::NewL(aMsg);
+}
+
+
+COstBaseRouter*	COstBaseRouter::NewL()
+{
+	LOG_MSG("COstWriteMsgEntry::NewL");
+
+	COstBaseRouter* self = new(ELeave) COstBaseRouter;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+}
+
+COstBaseRouter::COstBaseRouter()
+: iPortManager(NULL),
+  iProtRegistry(NULL),
+  iWriteMsgListener(NULL),
+  iWriteMsgQueue(1)  
+{
+	LOG_MSG("COstBaseRouter::COstBaseRouter");
+
+}
+
+COstBaseRouter::~COstBaseRouter()
+{	
+	LOG_MSG("COstBaseRouter::~COstBaseRouter");
+
+	SafeDelete(iPortManager);
+	SafeDelete(iProtRegistry);
+	
+	iWriteMsgQueue.ResetAndDestroy();	
+	iWriteMsgQueue.Close();
+}
+
+void COstBaseRouter::ConstructL()
+{
+	LOG_MSG("COstBaseRouter::ConstructL");
+
+	iPortManager = CDbgTrcPortMgr::NewL();	
+	iProtRegistry = COstProtRegistry::NewL();
+	
+	// check the target endianness
+	TUint32	test;
+	TUint8 *byte_alias = (TUint8 *)&test;
+	
+	// Write a specific 4-byte sequence and then read it as
+	// a 32-bit word.  Big-endian systems yield one value and
+	// little-endian systems yield another.
+	
+	byte_alias[ 0 ] = 0x12;
+	byte_alias[ 1 ] = 0x34;
+	byte_alias[ 2 ] = 0x56;
+	byte_alias[ 3 ] = 0x78;
+	
+	if (test == 0x12345678)
+		iIsBigEndian = ETrue;
+	else
+		iIsBigEndian = EFalse;			
+	
+	iSendMsgBuffer.Zero();
+	iRecvMsgBuffer.Zero();
+	
+	iWriteMsgQueue.Reset();
+}
+
+void COstBaseRouter::RegisterProtocol(const TOstProtIds aProtId, CDbgTrcSrvSession* aProtMsgListener, TBool aNeedHeader)
+{
+	LOG_MSG("COstBaseRouter::RegisterProtocol");
+
+	iProtRegistry->RegisterProtocol(aProtId, aProtMsgListener, aNeedHeader);
+	
+	// Initiate the reads once someone registers a protocol.
+	//ReadMessage();
+}
+
+void COstBaseRouter::UnRegisterProtocol(const TOstProtIds aProtId)
+{
+	LOG_MSG("COstBaseRouter::UnRegisterProtocol");
+
+	iProtRegistry->UnRegisterProtocol(aProtId);
+	
+	// if listener count is 0, cancel the reads as well.
+	if (!iProtRegistry->GetProtListenerCount())
+	{
+		CPortReader* reader = iPortManager->GetPortReader();
+		if (reader)
+		{
+			reader->Cancel();
+		}
+	}	
+}
+
+
+void COstBaseRouter::ReadMessage()
+{	
+	LOG_MSG("COstBaseRouter::ReadMessage");
+
+	CPortReader* reader = iPortManager->GetPortReader();
+	
+	if (reader)
+		reader->StartRead(this);
+}
+
+
+void COstBaseRouter::WriteMessageL(TDesC8& aMsg, CDbgTrcSrvSession* aProtMsgListener)
+{
+	LOG_MSG("COstBaseRouter::WriteMessage");
+	
+	iSendMsgBuffer.Zero();
+	iSendMsgBuffer.Append(aMsg);
+			
+	DoWriteMessageL(aProtMsgListener);
+}
+
+void COstBaseRouter::WriteMessageL(TDesC8& aMsg, CDbgTrcSrvSession* aProtMsgListener, TOstProtIds aProtId)
+{
+	LOG_MSG("COstBaseRouter::WriteMessage");	
+	
+	// write now, we use a fixed size array for the write message,
+	// look below for the commented implementation if necessary in the future.
+	iSendMsgBuffer.Zero();
+
+	TUint16 msgLength = aMsg.Length();
+	
+	TUint8 version = OST_PROTOCOL_VERSION;		
+	
+	iSendMsgBuffer.Append(&version, sizeof(TUint8));
+	iSendMsgBuffer.Append((TUint8*)&aProtId, sizeof(TUint8));
+	
+	TUint16 temp = msgLength; 
+	if (!iIsBigEndian)
+		temp = Swap2(msgLength);
+		
+	iSendMsgBuffer.Append((TUint8*)&temp, sizeof(TUint16));
+			
+	// now append the msg data
+	iSendMsgBuffer.Append(aMsg);
+		
+	DoWriteMessageL(aProtMsgListener);
+}
+
+
+/*
+TInt COstBaseRouter::WriteMessage(TDesC8& aMsg, CDbgTrcSrvSession* aProtMsgListener, TOstProtIds aProtId)
+{	
+	HBufC8* msgBuffer = HBufC8::New(aMsg.Length() + OST_HEADER_LENGTH);
+	
+	TUint16 msgLength = aMsg.Length();
+	
+	TUint8 version = OST_PROTOCOL_VERSION;		
+	
+	msgBuffer->Des().Append(&version, sizeof(TUint8));
+	msgBuffer->Des().Append((TUint8*)&aProtId, sizeof(TUint8));
+	
+	TUint16 temp = msgLength; 
+	if (!iIsBigEndian)
+		temp = Swap2(msgLength);
+		
+	msgBuffer->Des().Append((TUint8*)&temp, sizeof(TUint16));
+			
+	// now append the msg data
+	msgBuffer->Des().Append(aMsg);
+	
+	
+}
+*/
+
+void COstBaseRouter::DoWriteMessageL(CDbgTrcSrvSession* aProtMsgListener)
+{
+	LOG_MSG("COstBaseRouter::DoWriteMessage");
+
+	CPortWriter* writer = iPortManager->GetPortWriter();
+	
+	if(writer)
+	{
+		if (writer->IsBusy())
+		{
+			LOG_MSG("Writer busy, queuing up the write message");
+
+			// we are already writing a message
+			// so queue up this one, we only have to queue up one message for each connected client for writing.
+			COstWriteMsgEntry* writeMsgEntry = COstWriteMsgEntry::NewL(iSendMsgBuffer, aProtMsgListener);
+			iWriteMsgQueue.Append(writeMsgEntry);
+		}
+		else
+		{
+			// set the write listener for completing the request when the write is done
+			iWriteMsgListener = aProtMsgListener;	
+			writer->StartWrite(iSendMsgBuffer, this);
+		}
+	}
+}
+
+void COstBaseRouter::DataAvailable(TDesC8& aMsgData, TUint aLength)
+{
+	LOG_MSG("COstBaseRouter::DataAvailable");
+	LOG_MSG2("Received bytes : %d", aLength);	
+
+	TInt remainingBytes = aMsgData.Length();
+	const TUint8* recvMsgDataPtr = aMsgData.Ptr();
+	while (remainingBytes > 0)
+	{	
+		TInt bytesToCopy = remainingBytes;
+		TInt spaceAvailable = MAX_BUF_SIZE-iRecvMsgBuffer.Length();
+		if (spaceAvailable == 0) //should never happen, if this happens, then we will loose messages.
+			return;
+			
+		if (remainingBytes > spaceAvailable)
+		{
+			bytesToCopy = spaceAvailable;
+		}
+		
+		remainingBytes -= bytesToCopy;		
+		iRecvMsgBuffer.Append(recvMsgDataPtr, bytesToCopy);
+		recvMsgDataPtr += bytesToCopy;
+							
+		LOG_MSG2("Bytes copied: %d", bytesToCopy);
+		LOG_MSG2("Remaining bytes : %d", remainingBytes);
+					
+		//
+		// We could possibly get more than one message at a time, 
+		// so check until we have atleast as many bytes as the OST header.
+		//
+		LOG_MSG2("Total bytes in the buffer : %d", iRecvMsgBuffer.Length());
+		while (iRecvMsgBuffer.Length() > OST_HEADER_LENGTH)
+		{
+			LOG_MSG("No of received bytes > OST header length");
+
+			const TUint8* ptr = iRecvMsgBuffer.Ptr();
+
+			TUint8 version = ptr[VERS_FIELD_INDEX];
+			TUint8 protId  = ptr[PROTID_FIELD_INDEX];
+			
+			// There could be some junk bytes in the data.
+			// With the latest PCSuite/USB cable drivers, there seems to be some 
+			// junk bytes in the USB channel. Also we can only do this simple check 
+			// only at the beginning of the packet. The only check we have right now 
+			// for the OST base protocol is to check for the version and the protocol id	
+			if ( !( (version == OST_PROTOCOL_VERSION || version == OST_VERSION_PROTOCOL_VERSION) &&
+				 (protId == EOstProtTrk || protId == EOstProtTraceCore || protId == EOstProtOstSystem || protId == EOstProtTrcActivation) ) )
+			{
+				LOG_MSG2("Invalid version byte: %x", version);
+				LOG_MSG2("Invalid protocol byte: %x", protId);
+				RemoveNonOstBytes(iRecvMsgBuffer);
+			}
+				
+			LOG_MSG2("Total bytes in the buffer after removing non ost : %d", iRecvMsgBuffer.Length());					
+			if (iRecvMsgBuffer.Length()>OST_HEADER_LENGTH)
+			{
+				// reset ptr just incase if we have deleted some junk bytes
+				ptr = iRecvMsgBuffer.Ptr();
+				TUint16 packetLength = 0;
+				SwapBytes((TUint8*)&packetLength, &ptr[LENGTH_FIELD_INDEX], 2);
+			
+				LOG_MSG2("packet length is %d", packetLength);			
+
+				if (iRecvMsgBuffer.Length() >= (packetLength+OST_HEADER_LENGTH))
+				{
+					LOG_MSG("Got one complete message");
+
+					// got one complete message, complete the message if someone is listening for this message.
+					TBool needHeader;
+					CDbgTrcSrvSession* protMsgListener = iProtRegistry->GetProtListenerForProtId((TOstProtIds)protId, needHeader);
+					
+					if (protMsgListener)
+					{
+						LOG_MSG("Found a listener");
+
+						TPtrC8 completeMessage;
+						// check to see if we need to strip the header or not.
+						if (needHeader)				
+							completeMessage.Set(iRecvMsgBuffer.Ptr(), packetLength+OST_HEADER_LENGTH);
+						else
+							completeMessage.Set(iRecvMsgBuffer.Ptr()+OST_HEADER_LENGTH, packetLength);
+							
+						TRAPD(err, protMsgListener->MessageAvailableL(completeMessage));
+						if (err != KErrNone)
+						    LOG_MSG2("Failed to deliver the message: %d", err);
+					}	
+				
+					LOG_MSG2("Deleting bytes in the recieve buffer: %d", packetLength+OST_HEADER_LENGTH);
+
+					// now remove this message from our buffer as its already given to the listener				
+					iRecvMsgBuffer.Delete(0, packetLength+OST_HEADER_LENGTH);
+					
+					LOG_MSG2("Remaining bytes in the recieve buffer: %d", iRecvMsgBuffer.Length());				
+				}
+				else
+				{
+					// We have more bytes than the header but we have an incomplete message.
+					// So we break out here.
+					break; 
+				}
+			}	
+		}
+	}
+}
+
+void COstBaseRouter::DataWriteComplete(TInt aErrCode)
+{		
+	LOG_MSG("COstBaseRouter::DataWriteComplete");
+
+	if (iWriteMsgListener != NULL)
+	{
+		iWriteMsgListener->WriteComplete(aErrCode);
+		iWriteMsgListener = NULL;
+	}
+	else
+	{
+		LOG_MSG("Invalid write message listener, should never happen");
+	}	
+	
+	if (iWriteMsgQueue.Count() > 0)
+	{
+		LOG_MSG("Message found in write queue");
+		
+		COstMessage* ostMsg = iWriteMsgQueue[0]->iMessage;
+		iWriteMsgListener = iWriteMsgQueue[0]->iWriteMsgListener;
+		HBufC8* msg = ostMsg->iMsgBuffer;
+		
+		CPortWriter* writer = iPortManager->GetPortWriter();
+		if(writer)
+			writer->StartWrite(*msg, this);
+		
+		// now remove the message from the queue
+		SafeDelete(iWriteMsgQueue[0]);			
+		iWriteMsgQueue.Remove(0);		
+	}
+}
+
+void COstBaseRouter::GetPortConfig(TDes8& aConfigDes)
+{
+	LOG_MSG("COstBaseRouter::GetPortConfig");
+
+	iPortManager->GetPortConfig(aConfigDes);
+}
+
+TInt COstBaseRouter::SetPortConfig(TDesC8& aConfigDes)
+{
+	LOG_MSG("COstBaseRouter::SetPortConfig");
+
+	return iPortManager->SetPortConfig(aConfigDes);
+}
+
+TInt COstBaseRouter::OpenCommPortL()
+{
+	LOG_MSG("COstBaseRouter::OpenCommPort");
+
+	return iPortManager->OpenPortL();
+}
+
+TInt COstBaseRouter::CloseCommPort()
+{
+	LOG_MSG("COstBaseRouter::CloseCommPort");
+	
+	return iPortManager->ClosePort();
+}
+
+
+void COstBaseRouter::SwapBytes(TUint8* aTrgtData, const TUint8* aSrcData, TInt aLength)
+{	
+	LOG_MSG("COstBaseRouter::SwapBytes");
+	
+	if (iIsBigEndian)
+	{
+		Mem::Copy(aTrgtData, aSrcData, aLength);
+	}
+	else
+	{
+		for (int i=aLength-1, j=0; i>=0; i--, j++)
+			aTrgtData[j] = aSrcData[i];
+	}		
+}
+
+
+void COstBaseRouter::RemoveNonOstBytes(TDes8& aMsgBuffer)
+{
+	LOG_MSG("COstBaseRouter::RemoveNonOstBytes");	
+	// We need to check for non OST bytes only in the beginning of the packet.
+	// The only check we have right now for the OST base protocol
+	// is to check for the version and the protocol id	
+	const TUint8* msgDataPtr = aMsgBuffer.Ptr(); 				
+	// look for the version byte..
+	// if found, bail out and check for protocol byte
+	TUint length = aMsgBuffer.Length();
+	LOG_MSG2("Total bytes in the buffer: %d", length);
+	for (TInt i=VERS_FIELD_INDEX; i<length; i++)
+	{			
+		if (msgDataPtr[VERS_FIELD_INDEX] == OST_PROTOCOL_VERSION ||
+			msgDataPtr[VERS_FIELD_INDEX] == OST_VERSION_PROTOCOL_VERSION)	
+		{
+			// If we have more than one byte and the first byte seems to be the version byte
+			// then check to see whether the second byte is the protocol byte or not.
+			// if not, then delete the two bytes and start looking for version byte in the remaining bytes
+			if (aMsgBuffer.Length()>1)
+			{
+				if (msgDataPtr[PROTID_FIELD_INDEX] == EOstProtTrk || 
+					msgDataPtr[PROTID_FIELD_INDEX] == EOstProtTraceCore  ||
+					msgDataPtr[PROTID_FIELD_INDEX] == EOstProtOstSystem ||
+					msgDataPtr[PROTID_FIELD_INDEX] == EOstProtTrcActivation)				
+				{
+					LOG_MSG("Found a valid packet");
+					break;					
+				}					
+				else
+				{
+					// we didn't find the version byte and the protocol byte together
+					// so delete the two bytes
+					LOG_MSG2("Deleting junk bytes, unexpected version: %x", msgDataPtr[VERS_FIELD_INDEX]);
+					LOG_MSG2("Deleting junk bytes, unexpected protocol id: %x", msgDataPtr[PROTID_FIELD_INDEX]);
+
+					aMsgBuffer.Delete(VERS_FIELD_INDEX, 2);
+					i++; //deleting more than one byte, so increment one more time here.
+				}					
+			}
+			else
+			{
+				// Special case handling when there is only one remaining byte 
+				// and that byte happens to be the version byte
+				// This could be an invalid byte from out of protocol data, just happens to be the version byte.
+				// So delete this byte as well just so that we don't treat this byte as the version byte by mistake.
+				LOG_MSG2("Deleting one remaining byte, unexpected version: %x", msgDataPtr[VERS_FIELD_INDEX]);
+				aMsgBuffer.Delete(VERS_FIELD_INDEX, 1);			
+			}
+		}
+		else
+		{
+			// if the first byte is not the version byte, delete it
+			// it could be out of protocol data, we just need throw away
+			LOG_MSG2("Deleting junk byte, unexpected version: %x", msgDataPtr[VERS_FIELD_INDEX]);
+			aMsgBuffer.Delete(VERS_FIELD_INDEX, 1);
+		}
+	}		
+}