cbsref/csyrefplugins/csy27010/src/CommFrameReaderAo.cpp
changeset 44 8b72faa1200f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cbsref/csyrefplugins/csy27010/src/CommFrameReaderAo.cpp	Tue Jun 22 11:02:32 2010 +0100
@@ -0,0 +1,594 @@
+//
+// * Copyright 2004 Neusoft America Inc.
+// * All rights reserved.
+// * This component and the accompanying materials are made available
+// * under the terms of the Eclipse Public License v1.0
+// * which accompanies this distribution, and is available
+// * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+// *
+// * Contributors:
+// * Keith Collins (Neusoft America Inc.)  original software development and additional code and modifications.
+// * Thomas Gahagen (Neusoft America Inc.)  additional code and modifications.
+// * Zhen Yuan (Neusoft America Inc.)  additional code and modifications.
+// *
+// * Description:  This file contains the implementation for class CCommFrameReaderAo.
+// *               Class CCommFrameReaderAo is used to request a read from the serial port LDD.
+// *               Class CommFrameReaderAo is an active object and is run by the active
+// *               scheduler when the LDD has completed the read request.
+//
+
+// CommFrameReaderAo.cpp
+
+/** @file CommFrameReaderAo.cpp
+ *
+ * The file contains the implementation for class CCommFrameReaderAo.
+ * Class CCommFrameReaderAo is used to request a read from the serial port LDD.
+ * Class CommFrameReaderAo is an active object and is run by the active
+ * scheduler when the LDD has completed the read request
+ */
+
+// Need to add code to package together a frame and then send the
+// complete frame to the Mux object for defragmentation into a client msg.
+
+#include "CommFrameReaderAo.h"
+#include "Portfactory.h"
+#include "CsyMsgBufBPFrame.h"
+#include "Mux0710Protocol.h"
+#include "CsyDebugLogger.h"
+#include "ChannelMgrCtrl.h"
+#include "ChannelMgrCmdData.h"
+
+CCommFrameReaderAo* CCommFrameReaderAo::NewL(CPortFactory* aParent, CMux0710Protocol* aMux0710Protocol)
+/**
+ * This methods uses two phase construction and the cleanup stack to create
+ * an instance of class CCommFrameReaderAo.
+ * @param aParent - Pointer to parent
+ * @param aMux0710Protocol - Pointer to Mux 27.010 object
+ * @return Pointer to the created instance
+ */
+	{
+	_LOG_L4C1("CCommFrameReaderAo::NewL");
+
+	CCommFrameReaderAo* c = new (ELeave) CCommFrameReaderAo(aParent, aMux0710Protocol);
+	CleanupStack::PushL(c);
+	c->ConstructL();
+	CleanupStack::Pop();
+	return c;
+	}
+
+CCommFrameReaderAo::~CCommFrameReaderAo()
+/**
+ * Destructor. Cancel any outstanding request.
+ */
+	{
+	_LOG_L4C1("CCommFrameReaderAo::~CCommFrameReaderAo");
+	Cancel();
+	}
+
+CCommFrameReaderAo::CCommFrameReaderAo(CPortFactory* aParent, CMux0710Protocol* aMux0710Protocol)
+/**
+ * Constructor.  Pass priority of active object to base class.
+ * @param aParent - Pointer to parent
+ * @param aMux0710Protocol - Pointer to Mux 27.010 object
+ */
+: CCommReadWriteBaseAo(aParent, aMux0710Protocol, KFrameReaderAoPriority),
+  iFrameReaderState(ECsyWaitingForStartFlag)
+	{
+	}
+
+void CCommFrameReaderAo::ConstructL()
+/**
+ * Retrieve a pointer to the LDD comm port.
+ */
+    {
+	_LOG_L4C1("CCommFrameReaderAo::ConstructL");
+	SetBuffersL();
+	}
+
+void CCommFrameReaderAo::DoCancel()
+/**
+ * Cancel an outstanding request.
+ * @param void
+ */
+	{
+	_LOG_L4C1("CCommFrameReaderAo::DoCancel");
+
+	iCommPort->ReadCancel();
+	}
+
+void CCommFrameReaderAo::BasicOption()
+/**
+ * Basic option frames
+ * Note this has not been tested since DSample/P2 do not use basic option
+ */
+	{
+	TUint octet;
+	TBool frameData = EFalse;
+
+	TInt len = iBuf->Length();
+	TPtr8 ptr = iBuffer->Des();
+	_LOG_L3C2("Received %d bytes",len);
+
+	for (TInt loop = 0; loop < len; loop++)
+		{
+		octet = ptr[loop];
+
+		if (octet == KCsy0710StartEndFlag)
+			{
+			// Control bit
+			switch(iFrameReaderState)
+				{
+			case ECsyWaitingForStartFlag:
+				{
+				_LOG_L3C2("[0x%02x] Got start flag",octet);
+				iFrameReaderState = ECsyWaitingForFrameStart;
+
+				if (iFrameBuf == NULL)
+					{
+					// There is data to process - get a new frame
+					iFrameBuf = iMux0710Protocol->GetFreeFrameBuf();
+					if (iFrameBuf == NULL)
+						{
+						_LOG_L1C1("** No free frame buffer ** - ignoring frame");
+						break;
+						}
+					}
+				}
+				break;
+			case ECsyWaitingForFrameStart:
+				{
+				// disregard additional flag
+				}
+				break;
+			case ECsyWaitingForFrameData:
+				{
+				iFrameReaderState = ECsyWaitingForStartFlag;
+
+				// must be the end flag
+				_LOG_L3C2("[0x%02x] End of frame",octet);
+				if (iFrameBuf)
+					{
+					if(iFrameBuf->iMsg.Length())
+						{
+						// Frame holds something
+						AddToReceivedFramesList(iFrameBuf);
+						iFrameBuf = NULL;
+						}
+					else
+						{
+						_LOG_L1C1("** zero length frame **");
+						// MAF __ASSERT_DEBUG(EFalse, PANIC(KPanicIllegalState));
+						}
+					}
+				else
+					{
+					_LOG_L3C1("** no frame buffer! **");
+					}
+				}
+				break;
+			default:
+				// MAF __ASSERT_DEBUG(EFalse, PANIC(KPanicIllegalState));
+				_LOG_L1C2("** unexpected flag ** [iFrameReaderState=%d]",iFrameReaderState);
+				break;
+				}
+			}
+		else
+			{
+			if (iFrameReaderState == ECsyWaitingForFrameStart)
+				{
+				iFrameReaderState = ECsyWaitingForFrameData;
+				iFrameBuf->iMsg.Append(octet);
+				
+				#ifdef _DEBUG
+				// This variable should only be set if it debug
+				// Otherwise we get warnings when compiling with ARM v5
+				TUint dlcNum = octet >> 2;
+				#endif
+
+				_LOG_L3C3E("[0x%02x] dlcNum=%d", octet, dlcNum);
+				}
+			else
+				{
+				_LOG_L3C2("[0x%02x]",octet);
+				frameData = ETrue;
+				}
+			}
+
+		if (frameData)
+			{
+			// MAF __ASSERT_DEBUG((iFrameReaderState == ECsyWaitingForFrameData),PANIC(KPanicIllegalState));
+
+			TUint frameLen = (TUint) (iFrameBuf->iMsg.Length() + 1);
+			if (frameLen > KMaxAdvFrameSize)
+				{
+				_LOG_L1C3("** length %d will exceed max length %d **",
+					frameLen,KMaxFrameSize);
+				iFrameBuf->iMsg.Zero();		
+				iFrameReaderState = ECsyWaitingForStartFlag;
+				break;
+				}
+
+			frameData = EFalse;
+			iFrameBuf->iMsg.Append(octet);
+			}
+		}
+	}
+
+void CCommFrameReaderAo::AdvancedOption()
+/**
+ * Advanced option frames
+ */
+	{
+	TUint octet = 0;
+	TBool frameData = EFalse;
+
+	TInt len = iBuf->Length();
+	TPtr8 ptr = iBuffer->Des();
+	_LOG_L3C2("Received %d bytes",len);
+
+	TInt startVal = 0;
+
+	// Check processing (helps when we have lost sync with data due to read error)
+	if ((iFrameReaderState == ECsyWaitingForStartFlag)&&(len))
+		{
+		// We are on the hunt for the start flag
+		if (iESCRecved)
+			{
+			_LOG_L2C1("Escape flag set - ignore first octet");
+			iESCRecved = EFalse;
+			}
+		else
+			octet = ptr[0];
+
+		if (octet != KCsy0710StartEndFlag)
+			{
+			_LOG_L3C2("[0x%02x]",octet);
+			_LOG_L2C1("* Looking for the start flag *");
+			do
+				{
+				startVal++;
+				if (startVal == len)
+					break;
+
+				octet = ptr[startVal];
+
+				if (iESCRecved)
+					{
+					iESCRecved = EFalse;
+					continue;
+					}
+
+				if (octet == KCsy0710EscapeByte)
+					iESCRecved = ETrue;
+				}
+			while (octet != KCsy0710StartEndFlag);
+
+			_LOG_L2C2("Disregarded %d bytes",startVal);
+			}
+		}
+
+	// Do processing of the received buffer
+	for (TInt loop = startVal; loop < len; loop++)
+		{
+		octet = ptr[loop];
+
+		if (iESCRecved)
+			{
+			_LOG_L3C2("[0x%02x] - Recv ESC before, change this char",octet);
+			octet = (TUint8) (octet^(1<<5));
+			_LOG_L3C2("Changed to [0x%02x]",octet);
+			iESCRecved = EFalse;
+			frameData = ETrue;
+			}
+		else
+			{
+			if (octet == KCsy0710EscapeByte)
+				{
+				_LOG_L3C1("KCsy0710EscapeByte");
+				iESCRecved = ETrue;
+				}
+			else if (octet == KCsy0710StartEndFlag)
+				{
+				// Control bit
+				switch(iFrameReaderState)
+					{
+				case ECsyWaitingForFrameData:
+					{
+					iFrameReaderState = ECsyWaitingForStartFlag;
+					
+					if (iFrameBuf)
+						{
+						TInt frameLen = iFrameBuf->iMsg.Length();
+						if(frameLen > KAdvOptionHeaderSize)
+							{
+							TUint8 checkSum = iFrameBuf->iMsg[frameLen-1];
+							if (CheckFCS(iFrameBuf->iMsg,KAdvOptionHeaderSize,checkSum))
+								{
+								// must be the end flag
+								_LOG_L3C2("[0x%02x] End of frame",octet);
+								// Frame holds something
+								AddToReceivedFramesList(iFrameBuf);
+								iFrameBuf = NULL;
+								}
+							else
+								{
+								_LOG_L1C1("** checksum is incorrect - rejecting frame **");
+								iFrameBuf->iMsg.Zero();		
+								}
+							}
+						else
+							{
+							_LOG_L1C2("** Rejected incorrect length frame %d **",frameLen);
+							iFrameBuf->iMsg.Zero();		
+							}
+						}
+					else
+						{
+						_LOG_L3C1("** no frame buffer! **");
+						}
+
+					TInt check = loop+1;
+					if (check == len)
+						break;
+
+					// There are more bytes in this buffer to process
+					octet = ptr[check];
+					if (octet != KCsy0710StartEndFlag)
+						{
+						// Frames are back to back
+						_LOG_L2C1("* No start flag - assuming frames back to back *");
+						octet = KCsy0710StartEndFlag;
+						}
+					}
+					// deliberate fall through
+				case ECsyWaitingForStartFlag:
+					{
+					_LOG_L3C2("[0x%02x] Got start flag",octet);
+					iFrameReaderState = ECsyWaitingForFrameStart;
+
+					if (iFrameBuf == NULL)
+						{
+						// There is data to process - get a new frame
+						iFrameBuf = iMux0710Protocol->GetFreeFrameBuf();
+						if (iFrameBuf == NULL)
+							{
+							_LOG_L1C1("** No free frame buffer ** - ignoring frame");
+							// Note: GetFreeFrameBuf handles the flow control
+							break;
+							}
+						}
+					}
+					break;
+				case ECsyWaitingForFrameStart:
+					{
+					// disregard additional flag
+					}
+					break;
+				default:
+					_LOG_L1C2("** unexpected flag ** [iFrameReaderState=%d]",iFrameReaderState);
+					// MAF __ASSERT_DEBUG(EFalse, PANIC(KPanicIllegalState));
+					break;
+					}
+				}
+			else
+				{
+				if (iFrameReaderState == ECsyWaitingForFrameStart)
+					iFrameReaderState = ECsyWaitingForFrameData;
+
+				_LOG_L3C2("[0x%02x]",octet);
+				frameData = ETrue;
+				}
+			}
+
+		if (frameData)
+			{
+			frameData = EFalse;
+
+			// MAF __ASSERT_DEBUG((iFrameReaderState == ECsyWaitingForFrameData),PANIC(KPanicIllegalState));
+
+			if (iFrameBuf)
+				{
+				TUint frameLen = (TUint) (iFrameBuf->iMsg.Length() + 1);
+				if (frameLen > KMaxAdvFrameSize)
+					{
+					_LOG_L1C2("** length will exceed max length %d **",
+						KMaxFrameSize);
+					iFrameBuf->iMsg.Zero();		
+					iFrameReaderState = ECsyWaitingForStartFlag;
+					break;
+					}
+
+				iFrameBuf->iMsg.Append(octet);
+				}
+			else
+				{
+				// it should not be possible to enter this condition
+
+				_LOG_L1C2("** No frame buffer allocated for frame ** [iFrameReaderState=%d]",iFrameReaderState);
+				// MAF __ASSERT_DEBUG(EFalse,PANIC(KPanicIllegalState));
+				}
+			}
+		}
+	}
+
+void CCommFrameReaderAo::NonMuxed()
+	{
+	if (iMux0710Protocol->ParseATResponse(*iBuf) == KErrNone)
+		{
+		iFrameReaderState = ECsyWaitingForStartFlag;
+		_LOG_L3C1("ParseATResponse returned KErrNone");
+		}
+	}
+
+void CCommFrameReaderAo::RunL()
+/**
+ * This method is invoked by the active scheduler when the read request
+ * to the LDD has completed.
+ */
+    {
+	if (iStatus.Int())
+		{
+		_LOG_L3C1(" "); // please leave separator in
+		_LOG_L1C2("** CCommFrameReaderAo::RunL [iStatus %d] **",iStatus.Int());
+
+		// assumption here, whatever the error we will be able to repost
+		// another request to readoneormore from the serial device driver.
+
+		if (iFrameBuf)
+			{
+			iMux0710Protocol->AddFrameFreeQ(iFrameBuf);
+			iFrameBuf = NULL;
+			}
+
+		//reset state
+		iESCRecved = EFalse;
+		iFrameReaderState = ECsyWaitingForStartFlag;
+
+		iStatus = KRequestPending;
+ 		SetActive();
+		iCommPort->ReadOneOrMore(iStatus, *iBuf);
+		return;
+		}
+
+	if (iFrameBuf == NULL)
+		{
+		// Only show this log if start of a new frame
+		_LOG_L3C1(" "); // please leave separator in
+		_LOG_L3C1("CCommFrameReaderAo::RunL - start of read");
+		}
+
+	if (!iMux0710Protocol->IsMuxModeEnabled())
+		{
+		NonMuxed();
+		}
+	else
+		{
+		// mux mode is enabled
+		// process recv data according to our current state
+
+#ifndef _27010ADVANCEOPTION
+
+		BasicOption();
+
+#else
+		AdvancedOption();
+
+#endif
+		}
+
+	if (!IsActive())
+		{
+		iStatus = KRequestPending;
+ 		SetActive();
+		iCommPort->ReadOneOrMore(iStatus, *iBuf);
+		}
+	}
+
+void CCommFrameReaderAo::Read()
+/**
+ * This method is called to start the process to read an ascii string
+ * (e.g. response to initial AT+CMUX=0,0,5 command) or a frame from 
+ * the serial port LDD. 
+ * Note that this method will only be called once and then the RunL
+ * will handle the reading of the comm port.
+ */
+	{
+	_LOG_L4C1(">>CCommFrameReaderAo::Read");
+
+	if (!IsActive())
+		{
+		_LOG_L3C1("Read not active");
+
+		// Set the object active
+		iStatus = KRequestPending;
+ 		SetActive();
+		iCommPort->ReadOneOrMore(iStatus, *iBuf);
+		}
+	else
+		{
+		_LOG_L2C1("** Already active **");
+		}
+
+	_LOG_L4C1("<<CCommFrameReaderAo::Read");
+    }
+
+void CCommFrameReaderAo::ReadCancel()
+/**
+ * Cancel a read request.
+ */
+	{
+	_LOG_L4C1(">>CCommFrameReaderAo::ReadCancel");
+
+	iCommPort->ReadCancel();
+	if (iFrameBuf)
+		{
+		// return buffer to free frame queue
+		iMux0710Protocol->AddFrameFreeQ(iFrameBuf);
+		iFrameBuf = NULL;
+		}
+
+	_LOG_L4C1("<<CCommFrameReaderAo::ReadCancel");
+	}
+
+TBool CCommFrameReaderAo::CheckFCS(TDes8& aBuffer, TInt aLen, TUint8 aSuppliedChecksum)
+/**
+ * This method checks the checksum for the specified buffer with the 
+ * specified length.
+ *
+ * @param aBuffer - Data 
+ * @param aLen    - Number of bytes in the Buffer for which CheckSum to be calculated
+ * @return ETrue if checksum is okay
+ */
+	{
+	TUint8 frameCheckSum = 0xFF;
+
+	for (TInt i=0; i < aLen; i++)
+		{
+		frameCheckSum = crctable[(frameCheckSum ^ aBuffer[i])];
+		}
+
+	// One's Complement
+	frameCheckSum = crctable[(frameCheckSum ^ aSuppliedChecksum)];
+
+	if (frameCheckSum == 0xCF)
+		return ETrue;
+
+	return EFalse;
+	}
+
+void CCommFrameReaderAo::AddToReceivedFramesList(CCsyMsgBufBpFrame* aBpFrame)
+/**
+ * This method is called by the comm frame reader to add the specified
+ * received frame to a c32 port interface queue. The specific C32 port 
+ * interface object is determined from the DLC number embedded in the frame.
+ *
+ * @param aBpFrame - Pointer to the received frame
+ */
+	{
+	_LOG_L4C1(">>CCommFrameReaderAo::AddToReceivedFramesList");
+
+	TUint8 dlcNum = aBpFrame->GetDlcNum();
+
+	_LOG_L4C2("dlcNum=%d", dlcNum);
+	_LOG_L4C2("frameType=0x%x", aBpFrame->GetFrameType());
+
+	// check for a message for the control channel
+	if (dlcNum == 0)
+		{
+		iParent->GetControlChannel()->ProcessRecvFrame(aBpFrame);
+		}
+	else
+		{
+		CChannelMgrCmdData* channel = iParent->FindChannelMgrByDlcNum(dlcNum);
+		if (channel != NULL)
+			channel->ProcessRecvFrame(aBpFrame);
+		else
+			{
+			_LOG_L1C2("** No port defined for dlcNum=%d **", dlcNum);
+			iMux0710Protocol->AddFrameFreeQ(aBpFrame);
+			}
+		}
+
+	_LOG_L4C1("<<CCommFrameReaderAo::AddToReceivedFramesList");
+	}
+