diff -r 000000000000 -r c6b0df440bee dbgagents/trkagent/dbgtrccomm/server/ostbaserouter.cpp --- /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 +#include +#include + +#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; i1) + { + 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); + } + } +}