dbgagents/trkagent/dbgtrccomm/server/ostbaserouter.cpp
changeset 0 c6b0df440bee
equal deleted inserted replaced
-1:000000000000 0:c6b0df440bee
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32debug.h>
       
    20 #include <e32base.h>
       
    21 #include <e32cons.h>
       
    22 
       
    23 #include "logging.h"
       
    24 #include "dbgtrcportmgr.h"
       
    25 #include "ostprotregistry.h"
       
    26 #include "portreader.h"
       
    27 #include "portwriter.h"
       
    28 #include "dbgtrcsrvsession.h"
       
    29 #include "ostmessage.h"
       
    30 #include "ostbaserouter.h"
       
    31 
       
    32 // Static functions
       
    33 
       
    34 //
       
    35 // Swap2
       
    36 //
       
    37 // Byte-swaps a 2-byte value.  Used to convert to/from little/big endian.
       
    38 //
       
    39 static TUint16 Swap2(TUint16 aSource)
       
    40 {
       
    41 	TUint16 dest = 0;
       
    42 	for (TInt i=0; i<2; i++)
       
    43 	{
       
    44 		dest <<= 8;
       
    45 		dest |= aSource & 0xFF;
       
    46 		aSource >>= 8;
       
    47 	}
       
    48 	
       
    49 	return dest;
       
    50 } 
       
    51 
       
    52 COstWriteMsgEntry* COstWriteMsgEntry::NewL(TDesC8& aMsg, CDbgTrcSrvSession* aMsgListener)
       
    53 {
       
    54 	LOG_MSG("COstWriteMsgEntry::NewL");
       
    55 
       
    56 	COstWriteMsgEntry* self = new(ELeave) COstWriteMsgEntry(aMsgListener);
       
    57 	CleanupStack::PushL(self);
       
    58 	self->ConstructL(aMsg);
       
    59 	CleanupStack::Pop(self);
       
    60 	return self;
       
    61 }
       
    62 
       
    63 COstWriteMsgEntry::COstWriteMsgEntry(CDbgTrcSrvSession* aMsgListener)
       
    64 : iMessage(NULL),
       
    65   iWriteMsgListener(aMsgListener)
       
    66 {
       
    67 	LOG_MSG("COstWriteMsgEntry::COstWriteMsgEntry");
       
    68 
       
    69 
       
    70 }
       
    71 
       
    72 COstWriteMsgEntry::~COstWriteMsgEntry()
       
    73 {
       
    74 	LOG_MSG("COstWriteMsgEntry::~COstWriteMsgEntry");
       
    75 
       
    76 	SafeDelete(iMessage);
       
    77 	iWriteMsgListener = NULL; //don't delete the listener since we don't really own it.
       
    78 }
       
    79 
       
    80 void COstWriteMsgEntry::ConstructL(TDesC8& aMsg)
       
    81 {
       
    82 	LOG_MSG("COstWriteMsgEntry::ConstructL");
       
    83 
       
    84 	iMessage = COstMessage::NewL(aMsg);
       
    85 }
       
    86 
       
    87 
       
    88 COstBaseRouter*	COstBaseRouter::NewL()
       
    89 {
       
    90 	LOG_MSG("COstWriteMsgEntry::NewL");
       
    91 
       
    92 	COstBaseRouter* self = new(ELeave) COstBaseRouter;
       
    93 	CleanupStack::PushL(self);
       
    94 	self->ConstructL();
       
    95 	CleanupStack::Pop(self);
       
    96 	return self;
       
    97 }
       
    98 
       
    99 COstBaseRouter::COstBaseRouter()
       
   100 : iPortManager(NULL),
       
   101   iProtRegistry(NULL),
       
   102   iWriteMsgListener(NULL),
       
   103   iWriteMsgQueue(1)  
       
   104 {
       
   105 	LOG_MSG("COstBaseRouter::COstBaseRouter");
       
   106 
       
   107 }
       
   108 
       
   109 COstBaseRouter::~COstBaseRouter()
       
   110 {	
       
   111 	LOG_MSG("COstBaseRouter::~COstBaseRouter");
       
   112 
       
   113 	SafeDelete(iPortManager);
       
   114 	SafeDelete(iProtRegistry);
       
   115 	
       
   116 	iWriteMsgQueue.ResetAndDestroy();	
       
   117 	iWriteMsgQueue.Close();
       
   118 }
       
   119 
       
   120 void COstBaseRouter::ConstructL()
       
   121 {
       
   122 	LOG_MSG("COstBaseRouter::ConstructL");
       
   123 
       
   124 	iPortManager = CDbgTrcPortMgr::NewL();	
       
   125 	iProtRegistry = COstProtRegistry::NewL();
       
   126 	
       
   127 	// check the target endianness
       
   128 	TUint32	test;
       
   129 	TUint8 *byte_alias = (TUint8 *)&test;
       
   130 	
       
   131 	// Write a specific 4-byte sequence and then read it as
       
   132 	// a 32-bit word.  Big-endian systems yield one value and
       
   133 	// little-endian systems yield another.
       
   134 	
       
   135 	byte_alias[ 0 ] = 0x12;
       
   136 	byte_alias[ 1 ] = 0x34;
       
   137 	byte_alias[ 2 ] = 0x56;
       
   138 	byte_alias[ 3 ] = 0x78;
       
   139 	
       
   140 	if (test == 0x12345678)
       
   141 		iIsBigEndian = ETrue;
       
   142 	else
       
   143 		iIsBigEndian = EFalse;			
       
   144 	
       
   145 	iSendMsgBuffer.Zero();
       
   146 	iRecvMsgBuffer.Zero();
       
   147 	
       
   148 	iWriteMsgQueue.Reset();
       
   149 }
       
   150 
       
   151 void COstBaseRouter::RegisterProtocol(const TOstProtIds aProtId, CDbgTrcSrvSession* aProtMsgListener, TBool aNeedHeader)
       
   152 {
       
   153 	LOG_MSG("COstBaseRouter::RegisterProtocol");
       
   154 
       
   155 	iProtRegistry->RegisterProtocol(aProtId, aProtMsgListener, aNeedHeader);
       
   156 	
       
   157 	// Initiate the reads once someone registers a protocol.
       
   158 	//ReadMessage();
       
   159 }
       
   160 
       
   161 void COstBaseRouter::UnRegisterProtocol(const TOstProtIds aProtId)
       
   162 {
       
   163 	LOG_MSG("COstBaseRouter::UnRegisterProtocol");
       
   164 
       
   165 	iProtRegistry->UnRegisterProtocol(aProtId);
       
   166 	
       
   167 	// if listener count is 0, cancel the reads as well.
       
   168 	if (!iProtRegistry->GetProtListenerCount())
       
   169 	{
       
   170 		CPortReader* reader = iPortManager->GetPortReader();
       
   171 		if (reader)
       
   172 		{
       
   173 			reader->Cancel();
       
   174 		}
       
   175 	}	
       
   176 }
       
   177 
       
   178 
       
   179 void COstBaseRouter::ReadMessage()
       
   180 {	
       
   181 	LOG_MSG("COstBaseRouter::ReadMessage");
       
   182 
       
   183 	CPortReader* reader = iPortManager->GetPortReader();
       
   184 	
       
   185 	if (reader)
       
   186 		reader->StartRead(this);
       
   187 }
       
   188 
       
   189 
       
   190 void COstBaseRouter::WriteMessageL(TDesC8& aMsg, CDbgTrcSrvSession* aProtMsgListener)
       
   191 {
       
   192 	LOG_MSG("COstBaseRouter::WriteMessage");
       
   193 	
       
   194 	iSendMsgBuffer.Zero();
       
   195 	iSendMsgBuffer.Append(aMsg);
       
   196 			
       
   197 	DoWriteMessageL(aProtMsgListener);
       
   198 }
       
   199 
       
   200 void COstBaseRouter::WriteMessageL(TDesC8& aMsg, CDbgTrcSrvSession* aProtMsgListener, TOstProtIds aProtId)
       
   201 {
       
   202 	LOG_MSG("COstBaseRouter::WriteMessage");	
       
   203 	
       
   204 	// write now, we use a fixed size array for the write message,
       
   205 	// look below for the commented implementation if necessary in the future.
       
   206 	iSendMsgBuffer.Zero();
       
   207 
       
   208 	TUint16 msgLength = aMsg.Length();
       
   209 	
       
   210 	TUint8 version = OST_PROTOCOL_VERSION;		
       
   211 	
       
   212 	iSendMsgBuffer.Append(&version, sizeof(TUint8));
       
   213 	iSendMsgBuffer.Append((TUint8*)&aProtId, sizeof(TUint8));
       
   214 	
       
   215 	TUint16 temp = msgLength; 
       
   216 	if (!iIsBigEndian)
       
   217 		temp = Swap2(msgLength);
       
   218 		
       
   219 	iSendMsgBuffer.Append((TUint8*)&temp, sizeof(TUint16));
       
   220 			
       
   221 	// now append the msg data
       
   222 	iSendMsgBuffer.Append(aMsg);
       
   223 		
       
   224 	DoWriteMessageL(aProtMsgListener);
       
   225 }
       
   226 
       
   227 
       
   228 /*
       
   229 TInt COstBaseRouter::WriteMessage(TDesC8& aMsg, CDbgTrcSrvSession* aProtMsgListener, TOstProtIds aProtId)
       
   230 {	
       
   231 	HBufC8* msgBuffer = HBufC8::New(aMsg.Length() + OST_HEADER_LENGTH);
       
   232 	
       
   233 	TUint16 msgLength = aMsg.Length();
       
   234 	
       
   235 	TUint8 version = OST_PROTOCOL_VERSION;		
       
   236 	
       
   237 	msgBuffer->Des().Append(&version, sizeof(TUint8));
       
   238 	msgBuffer->Des().Append((TUint8*)&aProtId, sizeof(TUint8));
       
   239 	
       
   240 	TUint16 temp = msgLength; 
       
   241 	if (!iIsBigEndian)
       
   242 		temp = Swap2(msgLength);
       
   243 		
       
   244 	msgBuffer->Des().Append((TUint8*)&temp, sizeof(TUint16));
       
   245 			
       
   246 	// now append the msg data
       
   247 	msgBuffer->Des().Append(aMsg);
       
   248 	
       
   249 	
       
   250 }
       
   251 */
       
   252 
       
   253 void COstBaseRouter::DoWriteMessageL(CDbgTrcSrvSession* aProtMsgListener)
       
   254 {
       
   255 	LOG_MSG("COstBaseRouter::DoWriteMessage");
       
   256 
       
   257 	CPortWriter* writer = iPortManager->GetPortWriter();
       
   258 	
       
   259 	if(writer)
       
   260 	{
       
   261 		if (writer->IsBusy())
       
   262 		{
       
   263 			LOG_MSG("Writer busy, queuing up the write message");
       
   264 
       
   265 			// we are already writing a message
       
   266 			// so queue up this one, we only have to queue up one message for each connected client for writing.
       
   267 			COstWriteMsgEntry* writeMsgEntry = COstWriteMsgEntry::NewL(iSendMsgBuffer, aProtMsgListener);
       
   268 			iWriteMsgQueue.Append(writeMsgEntry);
       
   269 		}
       
   270 		else
       
   271 		{
       
   272 			// set the write listener for completing the request when the write is done
       
   273 			iWriteMsgListener = aProtMsgListener;	
       
   274 			writer->StartWrite(iSendMsgBuffer, this);
       
   275 		}
       
   276 	}
       
   277 }
       
   278 
       
   279 void COstBaseRouter::DataAvailable(TDesC8& aMsgData, TUint aLength)
       
   280 {
       
   281 	LOG_MSG("COstBaseRouter::DataAvailable");
       
   282 	LOG_MSG2("Received bytes : %d", aLength);	
       
   283 
       
   284 	TInt remainingBytes = aMsgData.Length();
       
   285 	const TUint8* recvMsgDataPtr = aMsgData.Ptr();
       
   286 	while (remainingBytes > 0)
       
   287 	{	
       
   288 		TInt bytesToCopy = remainingBytes;
       
   289 		TInt spaceAvailable = MAX_BUF_SIZE-iRecvMsgBuffer.Length();
       
   290 		if (spaceAvailable == 0) //should never happen, if this happens, then we will loose messages.
       
   291 			return;
       
   292 			
       
   293 		if (remainingBytes > spaceAvailable)
       
   294 		{
       
   295 			bytesToCopy = spaceAvailable;
       
   296 		}
       
   297 		
       
   298 		remainingBytes -= bytesToCopy;		
       
   299 		iRecvMsgBuffer.Append(recvMsgDataPtr, bytesToCopy);
       
   300 		recvMsgDataPtr += bytesToCopy;
       
   301 							
       
   302 		LOG_MSG2("Bytes copied: %d", bytesToCopy);
       
   303 		LOG_MSG2("Remaining bytes : %d", remainingBytes);
       
   304 					
       
   305 		//
       
   306 		// We could possibly get more than one message at a time, 
       
   307 		// so check until we have atleast as many bytes as the OST header.
       
   308 		//
       
   309 		LOG_MSG2("Total bytes in the buffer : %d", iRecvMsgBuffer.Length());
       
   310 		while (iRecvMsgBuffer.Length() > OST_HEADER_LENGTH)
       
   311 		{
       
   312 			LOG_MSG("No of received bytes > OST header length");
       
   313 
       
   314 			const TUint8* ptr = iRecvMsgBuffer.Ptr();
       
   315 
       
   316 			TUint8 version = ptr[VERS_FIELD_INDEX];
       
   317 			TUint8 protId  = ptr[PROTID_FIELD_INDEX];
       
   318 			
       
   319 			// There could be some junk bytes in the data.
       
   320 			// With the latest PCSuite/USB cable drivers, there seems to be some 
       
   321 			// junk bytes in the USB channel. Also we can only do this simple check 
       
   322 			// only at the beginning of the packet. The only check we have right now 
       
   323 			// for the OST base protocol is to check for the version and the protocol id	
       
   324 			if ( !( (version == OST_PROTOCOL_VERSION || version == OST_VERSION_PROTOCOL_VERSION) &&
       
   325 				 (protId == EOstProtTrk || protId == EOstProtTraceCore || protId == EOstProtOstSystem || protId == EOstProtTrcActivation) ) )
       
   326 			{
       
   327 				LOG_MSG2("Invalid version byte: %x", version);
       
   328 				LOG_MSG2("Invalid protocol byte: %x", protId);
       
   329 				RemoveNonOstBytes(iRecvMsgBuffer);
       
   330 			}
       
   331 				
       
   332 			LOG_MSG2("Total bytes in the buffer after removing non ost : %d", iRecvMsgBuffer.Length());					
       
   333 			if (iRecvMsgBuffer.Length()>OST_HEADER_LENGTH)
       
   334 			{
       
   335 				// reset ptr just incase if we have deleted some junk bytes
       
   336 				ptr = iRecvMsgBuffer.Ptr();
       
   337 				TUint16 packetLength = 0;
       
   338 				SwapBytes((TUint8*)&packetLength, &ptr[LENGTH_FIELD_INDEX], 2);
       
   339 			
       
   340 				LOG_MSG2("packet length is %d", packetLength);			
       
   341 
       
   342 				if (iRecvMsgBuffer.Length() >= (packetLength+OST_HEADER_LENGTH))
       
   343 				{
       
   344 					LOG_MSG("Got one complete message");
       
   345 
       
   346 					// got one complete message, complete the message if someone is listening for this message.
       
   347 					TBool needHeader;
       
   348 					CDbgTrcSrvSession* protMsgListener = iProtRegistry->GetProtListenerForProtId((TOstProtIds)protId, needHeader);
       
   349 					
       
   350 					if (protMsgListener)
       
   351 					{
       
   352 						LOG_MSG("Found a listener");
       
   353 
       
   354 						TPtrC8 completeMessage;
       
   355 						// check to see if we need to strip the header or not.
       
   356 						if (needHeader)				
       
   357 							completeMessage.Set(iRecvMsgBuffer.Ptr(), packetLength+OST_HEADER_LENGTH);
       
   358 						else
       
   359 							completeMessage.Set(iRecvMsgBuffer.Ptr()+OST_HEADER_LENGTH, packetLength);
       
   360 							
       
   361 						TRAPD(err, protMsgListener->MessageAvailableL(completeMessage));
       
   362 						if (err != KErrNone)
       
   363 						    LOG_MSG2("Failed to deliver the message: %d", err);
       
   364 					}	
       
   365 				
       
   366 					LOG_MSG2("Deleting bytes in the recieve buffer: %d", packetLength+OST_HEADER_LENGTH);
       
   367 
       
   368 					// now remove this message from our buffer as its already given to the listener				
       
   369 					iRecvMsgBuffer.Delete(0, packetLength+OST_HEADER_LENGTH);
       
   370 					
       
   371 					LOG_MSG2("Remaining bytes in the recieve buffer: %d", iRecvMsgBuffer.Length());				
       
   372 				}
       
   373 				else
       
   374 				{
       
   375 					// We have more bytes than the header but we have an incomplete message.
       
   376 					// So we break out here.
       
   377 					break; 
       
   378 				}
       
   379 			}	
       
   380 		}
       
   381 	}
       
   382 }
       
   383 
       
   384 void COstBaseRouter::DataWriteComplete(TInt aErrCode)
       
   385 {		
       
   386 	LOG_MSG("COstBaseRouter::DataWriteComplete");
       
   387 
       
   388 	if (iWriteMsgListener != NULL)
       
   389 	{
       
   390 		iWriteMsgListener->WriteComplete(aErrCode);
       
   391 		iWriteMsgListener = NULL;
       
   392 	}
       
   393 	else
       
   394 	{
       
   395 		LOG_MSG("Invalid write message listener, should never happen");
       
   396 	}	
       
   397 	
       
   398 	if (iWriteMsgQueue.Count() > 0)
       
   399 	{
       
   400 		LOG_MSG("Message found in write queue");
       
   401 		
       
   402 		COstMessage* ostMsg = iWriteMsgQueue[0]->iMessage;
       
   403 		iWriteMsgListener = iWriteMsgQueue[0]->iWriteMsgListener;
       
   404 		HBufC8* msg = ostMsg->iMsgBuffer;
       
   405 		
       
   406 		CPortWriter* writer = iPortManager->GetPortWriter();
       
   407 		if(writer)
       
   408 			writer->StartWrite(*msg, this);
       
   409 		
       
   410 		// now remove the message from the queue
       
   411 		SafeDelete(iWriteMsgQueue[0]);			
       
   412 		iWriteMsgQueue.Remove(0);		
       
   413 	}
       
   414 }
       
   415 
       
   416 void COstBaseRouter::GetPortConfig(TDes8& aConfigDes)
       
   417 {
       
   418 	LOG_MSG("COstBaseRouter::GetPortConfig");
       
   419 
       
   420 	iPortManager->GetPortConfig(aConfigDes);
       
   421 }
       
   422 
       
   423 TInt COstBaseRouter::SetPortConfig(TDesC8& aConfigDes)
       
   424 {
       
   425 	LOG_MSG("COstBaseRouter::SetPortConfig");
       
   426 
       
   427 	return iPortManager->SetPortConfig(aConfigDes);
       
   428 }
       
   429 
       
   430 TInt COstBaseRouter::OpenCommPortL()
       
   431 {
       
   432 	LOG_MSG("COstBaseRouter::OpenCommPort");
       
   433 
       
   434 	return iPortManager->OpenPortL();
       
   435 }
       
   436 
       
   437 TInt COstBaseRouter::CloseCommPort()
       
   438 {
       
   439 	LOG_MSG("COstBaseRouter::CloseCommPort");
       
   440 	
       
   441 	return iPortManager->ClosePort();
       
   442 }
       
   443 
       
   444 
       
   445 void COstBaseRouter::SwapBytes(TUint8* aTrgtData, const TUint8* aSrcData, TInt aLength)
       
   446 {	
       
   447 	LOG_MSG("COstBaseRouter::SwapBytes");
       
   448 	
       
   449 	if (iIsBigEndian)
       
   450 	{
       
   451 		Mem::Copy(aTrgtData, aSrcData, aLength);
       
   452 	}
       
   453 	else
       
   454 	{
       
   455 		for (int i=aLength-1, j=0; i>=0; i--, j++)
       
   456 			aTrgtData[j] = aSrcData[i];
       
   457 	}		
       
   458 }
       
   459 
       
   460 
       
   461 void COstBaseRouter::RemoveNonOstBytes(TDes8& aMsgBuffer)
       
   462 {
       
   463 	LOG_MSG("COstBaseRouter::RemoveNonOstBytes");	
       
   464 	// We need to check for non OST bytes only in the beginning of the packet.
       
   465 	// The only check we have right now for the OST base protocol
       
   466 	// is to check for the version and the protocol id	
       
   467 	const TUint8* msgDataPtr = aMsgBuffer.Ptr(); 				
       
   468 	// look for the version byte..
       
   469 	// if found, bail out and check for protocol byte
       
   470 	TUint length = aMsgBuffer.Length();
       
   471 	LOG_MSG2("Total bytes in the buffer: %d", length);
       
   472 	for (TInt i=VERS_FIELD_INDEX; i<length; i++)
       
   473 	{			
       
   474 		if (msgDataPtr[VERS_FIELD_INDEX] == OST_PROTOCOL_VERSION ||
       
   475 			msgDataPtr[VERS_FIELD_INDEX] == OST_VERSION_PROTOCOL_VERSION)	
       
   476 		{
       
   477 			// If we have more than one byte and the first byte seems to be the version byte
       
   478 			// then check to see whether the second byte is the protocol byte or not.
       
   479 			// if not, then delete the two bytes and start looking for version byte in the remaining bytes
       
   480 			if (aMsgBuffer.Length()>1)
       
   481 			{
       
   482 				if (msgDataPtr[PROTID_FIELD_INDEX] == EOstProtTrk || 
       
   483 					msgDataPtr[PROTID_FIELD_INDEX] == EOstProtTraceCore  ||
       
   484 					msgDataPtr[PROTID_FIELD_INDEX] == EOstProtOstSystem ||
       
   485 					msgDataPtr[PROTID_FIELD_INDEX] == EOstProtTrcActivation)				
       
   486 				{
       
   487 					LOG_MSG("Found a valid packet");
       
   488 					break;					
       
   489 				}					
       
   490 				else
       
   491 				{
       
   492 					// we didn't find the version byte and the protocol byte together
       
   493 					// so delete the two bytes
       
   494 					LOG_MSG2("Deleting junk bytes, unexpected version: %x", msgDataPtr[VERS_FIELD_INDEX]);
       
   495 					LOG_MSG2("Deleting junk bytes, unexpected protocol id: %x", msgDataPtr[PROTID_FIELD_INDEX]);
       
   496 
       
   497 					aMsgBuffer.Delete(VERS_FIELD_INDEX, 2);
       
   498 					i++; //deleting more than one byte, so increment one more time here.
       
   499 				}					
       
   500 			}
       
   501 			else
       
   502 			{
       
   503 				// Special case handling when there is only one remaining byte 
       
   504 				// and that byte happens to be the version byte
       
   505 				// This could be an invalid byte from out of protocol data, just happens to be the version byte.
       
   506 				// So delete this byte as well just so that we don't treat this byte as the version byte by mistake.
       
   507 				LOG_MSG2("Deleting one remaining byte, unexpected version: %x", msgDataPtr[VERS_FIELD_INDEX]);
       
   508 				aMsgBuffer.Delete(VERS_FIELD_INDEX, 1);			
       
   509 			}
       
   510 		}
       
   511 		else
       
   512 		{
       
   513 			// if the first byte is not the version byte, delete it
       
   514 			// it could be out of protocol data, we just need throw away
       
   515 			LOG_MSG2("Deleting junk byte, unexpected version: %x", msgDataPtr[VERS_FIELD_INDEX]);
       
   516 			aMsgBuffer.Delete(VERS_FIELD_INDEX, 1);
       
   517 		}
       
   518 	}		
       
   519 }