cbsref/csyrefplugins/csy27010/src/CommFrameWriterAo.cpp
author hgs
Tue, 22 Jun 2010 11:02:32 +0100
changeset 44 8b72faa1200f
permissions -rw-r--r--
201024_02

//
// * 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 implemenation for the CCommFrameWriterAo class.
// *               This class is used to handle the write operations to the serial port
// *               logical device driver.
//

// CommFrameWriterAo.cpp

/** @file CommFrameWriterAo.cpp
 *
 * This file contains the implemenation for the CCommFrameWriterAo class.
 * This class is used to handle the write operations to the serial port
 * logical device driver.
 */

#include "CommFrameWriterAo.h"
#include "CsyMsgBufBPFrame.h"
#include "Mux0710Protocol.h"
#include "CsyDebugLogger.h"
#include "PortC32InterfaceBase.h"

CCommFrameWriterAo* CCommFrameWriterAo::NewL(CPortFactory* aParent, CMux0710Protocol* aMux0710Protocol)
/**
 * This method uses two phase construction and the cleanup stack to
 * create an instance of class CCommFrameWriterAo. 
 *
 * @param aParent - Pointer to the parent object
 * @param aMux0710Protocol - Pointer to mux protocol object
 * @return Pointer to new instance of CCommFrameWriterAo
 */
    {
	_LOG_L4C1("CCommFrameWriterAo::NewL");

    CCommFrameWriterAo* obj = new (ELeave) CCommFrameWriterAo(aParent, aMux0710Protocol);
    CleanupStack::PushL(obj);
    obj->ConstructL();
    CleanupStack::Pop();
    return (obj);
    }


CCommFrameWriterAo::~CCommFrameWriterAo()
/**
 * Destructor.
 */
    {
	_LOG_L4C1("CCommFrameWriterAo::~CCommFrameWriterAo");

    Cancel();

 	// Remove the frames in Write Buf List
	CCsyMsgBufBpFrame* frame;
	iWriteFrameBufIter.SetToFirst();
	while ((frame = iWriteFrameBufIter++) != NULL)
		{
		iWriteFrameBufList.Remove(*frame);
		delete frame;
	 	}

 	// Remove the frames in waiting list
	iWaitingForFcOffIter.SetToFirst();
	while ((frame = iWaitingForFcOffIter++) != NULL)
		{
		iWaitingForFcOffList.Remove(*frame);
		delete frame;
	 	}
   }

CCommFrameWriterAo::CCommFrameWriterAo(CPortFactory* aParent, CMux0710Protocol* aMux0710Protocol)
/**
 * Constructor.
 * @param aParent - Pointer to the parent object
 * @param aMux0710Protocol - Pointer to mux protocol object
 */
:	CCommReadWriteBaseAo(aParent, aMux0710Protocol, KFrameWriterAoPriority),
	iWriteFrameBufList(_FOFF(CCsyMsgBufBpFrame, iMsgLink)),
	iWriteFrameBufIter(iWriteFrameBufList),
	iWaitingForFcOffList(_FOFF(CCsyMsgBufBpFrame, iMsgLink)),
	iWaitingForFcOffIter(iWaitingForFcOffList)
	{}


void CCommFrameWriterAo::ConstructL()
/**
 * Safe constructor
 */
    {
	_LOG_L4C1("CCommFrameWriterAo::ConstructL");
	SetBuffersL();
    }

void CCommFrameWriterAo::RunL()
/**
 * This method is called when a write to the LDD completes.
 */
	{
	_LOG_L4C1(" ");
	_LOG_L4C2(">>CCommFrameWriterAo::RunL [iStatus=%d] - written to LDD",
		iStatus.Int());

	if (iStatus.Int())
		{
		_LOG_L1C2("** Error writing to LDD ** [iStatus=%d]",iStatus.Int());

		if (!iCompleteWhenSent)
			{
			// The frame being sent was not the last or only one for this dlc, other
			// frames exist

			// go through list and remove other frames to send for this dlc
			RemoveAnyDlcFramesOnWriteList(iDlcNum, EFalse);

			iCompleteWhenSent = ETrue;
			}
		}

	if (iCompleteWhenSent)
		{
		iCompleteWhenSent = EFalse;

		_LOG_L3C2("Complete write [iDlcNum=%d]",iDlcNum);
		CompleteWrite(iDlcNum,iStatus.Int());
		}

	// check for another message that needs to be sent to the baseband
	CCsyMsgBufBpFrame* bpFrame = GetFrameToWrite();
	if (bpFrame)
		{
		TInt ret = KErrNone;
		do
			{
			ret = WriteFrame(bpFrame);
			if (ret)
				{
				_LOG_L1C2("** Write frame failed [ret=%d] **",ret);
				if (!iCompleteWhenSent)
					{
					// go through list and remove other frames to send for this dlc
					RemoveAnyDlcFramesOnWriteList(iDlcNum, EFalse);
					}
				}

			// Loop around if there is an error and try and send the next frame
			}
			while (ret);
		}
	else
		{
		_LOG_L3C1("Finished all writes - nothing more to send to LDD");
		}

	_LOG_L4C1("<<CCommFrameWriterAo::RunL");
	_LOG_L3C1(" "); // please leave this separator in
	}

void CCommFrameWriterAo::DoCancel()
/**
 * Cancel a pending write
 */
    {
	_LOG_L4C1("CCommFrameWriterAo::DoCancel - cancelling LDD write");

	iCommPort->WriteCancel();

 	// Remove the frames in Write Buf List
	CCsyMsgBufBpFrame* frame;
	iWriteFrameBufIter.SetToFirst();
	while ((frame = iWriteFrameBufIter++) != NULL)
		{
		iWriteFrameBufList.Remove(*frame);
		iMux0710Protocol->AddFrameFreeQ(frame);
	 	}

 	// Remove the frames in waiting list
	iWaitingForFcOffIter.SetToFirst();
	while ((frame = iWaitingForFcOffIter++) != NULL)
		{
		iWaitingForFcOffList.Remove(*frame);
		iMux0710Protocol->AddFrameFreeQ(frame);
	 	}
    }

TInt CCommFrameWriterAo::Write(CCsyMsgBufBpFrame* aBpFrame,
							   TBool aHighPriority)
/**
 * This method is called to transmit a frame to the baseband.
 *
 * @param aBpFrame - Pointer to frame
 * @param aHighPriority - Flag to indicate a high priority frame
 */
    {
	_LOG_L4C3(">>CCommFrameWriterAo::Write [aBpFrame=0x%x, aHighPriority=%d]",
		aBpFrame,aHighPriority);

	TInt ret = KErrNone;

	// 1st check if we are already transmitting a frame
	if (!IsActive())
		{
		_LOG_L4C1("Not currently writing a frame");
		ret = WriteFrame(aBpFrame);
		}
	else
		{
		// add frame to the list of frames that need to be sent to the BP
		_LOG_L2C1("Already writing a frame - add to queue");
		AddToWaitingToSendList(aBpFrame, aHighPriority);
		}

	_LOG_L4C2("<<CCommFrameWriterAo::Write [ret=%d]",ret);
	return ret;
	}

TInt CCommFrameWriterAo::WriteFrame(CCsyMsgBufBpFrame* aBpFrame)
/**
 * This method is called to transmit a frame to the baseband.
 *
 * @param aBpFrame - Pointer to frame
 */
    {
	_LOG_L4C2(">>CCommFrameWriterAo::WriteFrame [aBpFrame=0x%x]",
		aBpFrame);

	TInt ret = KErrNone;

	iDlcNum = aBpFrame->MsgDlc();
	iCompleteWhenSent = aBpFrame->CompleteWhenSent();

	if (iBuf == NULL)
		{
		_LOG_L1C1("** Failure to alloc iBuf **");

		ret = KErrNoMemory;
		_LOG_L4C2("<<CCommFrameWriterAo::WriteFrame [ret=%d]",ret);
		return ret;
		}

//*********************************************************
// MAF tidy up
#ifdef _DEBUG
	//log out frame
	TInt len = aBpFrame->iMsg.Length();
	_LOG_L3C3("[0x%02x] Tx Got Start dlc=%d", aBpFrame->iMsg[0], aBpFrame->MsgDlc());
	for(TInt k = 1; k < len-1; k++)
		{
		_LOG_L3C2("[0x%02x]",aBpFrame->iMsg[k]);
		}
	_LOG_L3C2("[0x%02x] Tx Frame End", aBpFrame->iMsg[len-1]);
	if (iMux0710Protocol->IsMuxModeEnabled())
		{
		if ((aBpFrame->iMsg[2] & 0xEF) == KCsy0710CTLUIH)
			{
#ifdef __DEBUGLOGFILE__
			TBuf8<200> tt;
#else
			TBuf16<200> tt;
#endif
			tt.Copy(aBpFrame->iMsg);

			TInt ttLength = tt.Length();
			tt.SetLength(ttLength);
#ifdef __LOGDEBUGLEVELMINOR__
			_LOG_L3C3("Sent >>>> %d: %S", aBpFrame->iMsg[1] >> 2, &tt);
#endif
			}
		}
#endif
//*********************************************************

	// copy message to local buffer
#ifdef _27010ADVANCEOPTION

	if (iMux0710Protocol->IsMuxModeEnabled())
		{
		TInt length = aBpFrame->iMsg.Length() - 1;
		TUint8 mask = 1<<5;

		iBuf->Zero();

		 // start flag
		iBuf->Append(aBpFrame->iMsg[0]);

		// check data for flag or escape character
		for (TInt i=1; i < length; i++)
			{
			TUint8 tmp = aBpFrame->iMsg[i];
			if ((tmp == KCsy0710StartEndFlag)||(tmp== KCsy0710EscapeByte))
				{
				_LOG_L3C1("Adding escape byte");
				iBuf->Append(KCsy0710EscapeByte);
				tmp = (TUint8) (tmp^mask);
				}
			iBuf->Append(tmp);
			}

		//ending flag
		iBuf->Append(aBpFrame->iMsg[length]);  
		}
	else
		iBuf->Copy(aBpFrame->iMsg);

#else

	// Basic option - no escape chars
	iBuf->Copy(aBpFrame->iMsg);

#endif

	// free the caller's frame buffer
	iMux0710Protocol->AddFrameFreeQ(aBpFrame);

	// invoke LDD
	_LOG_L3C1("Sending to LDD");
	iStatus = KRequestPending; //MAF why is this being set to KRequestPending?
 	SetActive();
	iCommPort->Write(iStatus, *iBuf, iBuf->Length());

	_LOG_L4C2("<<CCommFrameWriterAo::WriteFrame [ret=%d]",ret);
	return ret;
	}

void CCommFrameWriterAo::WriteCancel()
/**
 * Cancel the current write operation.
 * @return void
 */
    {
    _LOG_L4C1("CCommFrameWriterAo::WriteCancel");
	Cancel();
    }

void CCommFrameWriterAo::AddToWaitingToSendList(CCsyMsgBufBpFrame* aBpFrame, TBool aHighPriority)
/**
 * This method is called to by C32 Interface objects to add
 * the specified frame to the baseband queue.
 *
 * @param aBpFrame - Pointer to the frame buffer
 * @param aHighPriority - Flag to indicate a high priority frame
 */
	{
	_LOG_L4C3(">>CCommFrameWriterAo::AddToWaitingToSendList [aBpFrame=0x%x,aHighPriority=%d]",
		aBpFrame, aHighPriority);

	if (aHighPriority)
		iWriteFrameBufList.AddFirst(*aBpFrame);
	else
		iWriteFrameBufList.AddLast(*aBpFrame);

	_LOG_L4C1("<<CCommFrameWriterAo::AddToWaitingToSendList");
	}

CCsyMsgBufBpFrame* CCommFrameWriterAo::GetFrameToWrite()
/**
 * This method checks the queue for a frame that needs to be sent
 * to the baseband.  If there is a message then deque it from the queue and
 * return a pointer to it, else return NULL.
 *
 * @return Pointer to the frame to be written or NULL
 */
	{
	_LOG_L4C1(">>CCommFrameWriterAo::GetFrameToWrite");

	CCsyMsgBufBpFrame* frame = NULL;
	if (!iWriteFrameBufList.IsEmpty())
		{
		frame = iWriteFrameBufList.First();
		if (frame)
			iWriteFrameBufList.Remove(*frame);
		}

	_LOG_L4C2("<<CCommFrameWriterAo::GetFrameToWrite [frame=0x%x]",frame);
	return frame;
	}

void CCommFrameWriterAo::RemoveAnyDlcFramesOnWriteList(TUint8 aDlcNum, TBool aPlaceOnWaitList)
/**
 * This method transfers any frames on the write list from the dlc specified
 * to the waiting list.
 *
 * @param aDlcNum is the dlc number of the frames to move to the waiting list
 * @param aPlaceOnWaitList indicates whether to free the frame or place onto the
 *        wait list.
 */
	{
	_LOG_L4C3(">>CCommFrameWriterAo::RemoveAnyDlcFramesOnWriteList [aDlcNum=%d, aPlaceOnWaitList=%d]",
		aDlcNum,aPlaceOnWaitList);

	if (iWriteFrameBufList.IsEmpty())
		{
		// No frames to transfer
		_LOG_L4C1("No frames on write list");
		}
	else
		{
		CCsyMsgBufBpFrame* frame = NULL;
		iWriteFrameBufIter.SetToFirst();
		while ((frame = iWriteFrameBufIter++) != NULL)
			{
			if (frame->GetDlcNum() == aDlcNum)
				{
				iWriteFrameBufList.Remove(*frame);
				if (aPlaceOnWaitList)
					{
					_LOG_L4C1("Transferring frame to wait list");
					iWaitingForFcOffList.AddLast(*frame);
					}
				else
					{
					// Adding frame to the free list
					iMux0710Protocol->AddFrameFreeQ(frame);
					}
				}
			}
		}

	_LOG_L4C1("<<CCommFrameWriterAo::RemoveAnyDlcFramesOnWriteList");
	}

void CCommFrameWriterAo::RemoveAnyDlcFramesFromWaitList(TUint8 aDlcNum, TBool aPlaceOnWriteList)
/**
 * This method transfers any frames on the waiting list from the dlc specified
 * to the write list.
 *
 * @param aDlcNum is the dlc number of the frames to move to the write list
 */
	{
	_LOG_L4C3(">>CCommFrameWriterAo::RemoveAnyDlcFramesFromWaitList [aDlcNum=%d,aPlaceOnWriteList=%d]",
		aDlcNum,aPlaceOnWriteList);

	if (iWaitingForFcOffList.IsEmpty())
		{
		// No frames to transfer
		_LOG_L4C1("No frames on waiting list");
		}
	else
		{
		TBool writeQueueWasEmpty = iWriteFrameBufList.IsEmpty();

		CCsyMsgBufBpFrame* frame = NULL;
		iWaitingForFcOffIter.SetToFirst();
		while ((frame = iWaitingForFcOffIter++) != NULL)
			{
			if (frame->GetDlcNum() == aDlcNum)
				{
				iWaitingForFcOffList.Remove(*frame);
				if (aPlaceOnWriteList)
					{
					_LOG_L4C1("Transferring frame to write list");
					iWriteFrameBufList.AddLast(*frame);
					}
				else
					{
					// Adding frame to the free list
					iMux0710Protocol->AddFrameFreeQ(frame);
					}
				}
			}

		if ((!iWriteFrameBufList.IsEmpty())&&(writeQueueWasEmpty)&&(!IsActive()))
			{
			_LOG_L4C1("Write queue was empty and not active - triggering write");
			frame = GetFrameToWrite();
			TInt ret = WriteFrame(frame);
			if (ret)
				{
				_LOG_L1C2("Write delayed frame failed [ret=%d]",ret);

				// Place the failed frame back on the list.
				iWriteFrameBufList.AddFirst(*frame);
				}
			}
		}

	_LOG_L4C1("<<CCommFrameWriterAo::RemoveAnyDlcFramesFromWaitList");
	}

void CCommFrameWriterAo::CompleteWrite(const TUint8 aDlcNum, TInt aStatus)
/**
 * This method calls the DLC port interface to complete the write request.
 *
 * @param aDlcNum - DLC number of the port
 */
	{
	_LOG_L4C3(">>CCommFrameWriterAo::CompleteWrite [aDlcNum=%d,aStatus=%d]",
		aDlcNum,aStatus);

	if (aDlcNum)
		{
		CPortC32InterfaceBase* port = iParent->FindPortC32Interface(aDlcNum);
		if (port)
			port->CompleteWriteRequest(aStatus);
		else
			{
			_LOG_L1C2("** Port does not exist for aDlcNum=%d **",
				aDlcNum);
			// MAF __ASSERT_DEBUG(EFalse,PANIC(KPanicIllegalState));
			}
		}
	else
		{
		// MAF tell mux control channel of send result
		}

	_LOG_L4C1("<<CCommFrameWriterAo::CompleteWrite");
	}