cbsref/csyrefplugins/csy27010/src/Mux0710Protocol.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 16:23:08 +0300
branchRCL_3
changeset 65 630d2f34d719
permissions -rw-r--r--
Revision: 201035 Kit: 201035

//
// * 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 the Mux0710Protocol class.
//

// Mux0710Protocol.cpp

/** @file Mux0710Protocol.cpp
 *
 */
 
#include "Mux0710Protocol.h"
#include "Portfactory.h"
#include "PortC32Interface.h"
#include "CsyMsgBufBPFrame.h"
#include "ChannelMgrCmdData.h"
#include "CommFrameWriterAo.h"
#include "CommFrameReaderAo.h"
#include "ChannelMgrCtrl.h"
#include "CsyDebugLogger.h"

// AT Commands
_LIT8(KATCmdAttention,     "ATE0\r");
_LIT8(KATCmdDisableEcho,   "ATE0Q0V1\r");
_LIT8(KATCmdReset,   "AT%b\r");
_LIT8(KATCmdSleep,   "AT%SLEEP=0\r");

const TInt KRetryCount = 2;

CMux0710Protocol* CMux0710Protocol::NewL(CPortFactory& aPortFactory)
/**
 * This static method uses 2-phase construction to create an instance of
 * this class.
 *
 * @return Pointer to the created object
 */
	{
	_LOG_L4C1("CMux0710Protocol::NewL");

	CMux0710Protocol* p = new(ELeave) CMux0710Protocol(aPortFactory);
	CleanupStack::PushL(p);
	p->ConstructL();
	CleanupStack::Pop(p);
	return p;
 	}

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

	// Release  Free Frame Memory 
	CCsyMsgBufBpFrame* aBpFrame;
    iFreeFrameBufIter.SetToFirst();
	while ((aBpFrame = iFreeFrameBufIter++) != NULL)
		{
		iFreeFrameBufList.Remove(*aBpFrame);
		delete  aBpFrame;
	 	}  

	delete iTimeouter;
	}

CMux0710Protocol::CMux0710Protocol(CPortFactory& aPortFactory)
/**
 * Constructor.
 *
 */
 : iPortFactory(aPortFactory),
   iMuxMgrState(ECsyWaitingForFlushResp),
   iFreeFrameBufList(_FOFF(CCsyMsgBufBpFrame, iMsgLink)),
   iFreeFrameBufIter(iFreeFrameBufList),
   iRetryCount(KRetryCount)
   	{}

void CMux0710Protocol::ConstructL()
/**
 * Allocate the memory for the free frames list.
 */
	{
	_LOG_L4C1("CMux0710Protocol::ConstructL");

	iTimeouter = CActiveTimeouter::NewL(*this);

	// allocate memory for the free frame buffer
	for (TUint i=0; i < KMaxFreeFrames; i++)
		{
		CCsyMsgBufBpFrame* aBpFrame = CCsyMsgBufBpFrame::NewL();
		iFreeFrameBufList.AddLast(*aBpFrame);
		}
	iFreeFrameCount = KMaxFreeFrames;
	}

CCsyMsgBufBpFrame* CMux0710Protocol::GetFreeFrameBuf(TBool aCheckFlowControlThresholds)
/**
 * Get a free frame buffer and then remove the buffer from
 * the free list.
 *
 * @return - Pointer to a frame buffer or NULL 
 */
	{
	_LOG_L4C2(">>CMux0710Protocol::GetFreeFrameBuf [aCheckFlowControlThresholds=%d]",
		aCheckFlowControlThresholds);

	CCsyMsgBufBpFrame* frame = NULL;
	if (!iFreeFrameBufList.IsEmpty())
		{
		frame = iFreeFrameBufList.First();
		if (frame)
			{
			iFreeFrameBufList.Remove(*frame);
			iFreeFrameCount--;
			_LOG_L4C2("iFreeFrameCount=%d",iFreeFrameCount);

			if ((aCheckFlowControlThresholds)&&(iFreeFrameCount < KStopDataDlcsThreshold))
				{
				// Need to enforce some flow control
				iEnforcingFlowControl = ETrue;

				if (iFreeFrameCount == 1)
					{
					// Only one frame free - that can be used to send the MSC command
					_LOG_L4C1("Drastic action! - 1 frame free");
					iPortFactory.StopAnyDlc();
					}
				else
					{
					_LOG_L4C2("Less than %d frames free",KStopDataDlcsThreshold);
					iPortFactory.FindActiveDataDlcToStop();
					}
				}

			frame->iMsg.Zero();
			frame->MsgDlc() = KCtrlChannelDlcNum;
			frame->CompleteWhenSent() = ETrue;
			}
		}

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

void CMux0710Protocol::AddFrameFreeQ(CCsyMsgBufBpFrame* aBpFrame)
/**
 * This method is called to add the specified frame buffer to the
 * free frame queue.
 *
 * @param aBpFrame - Pointer to the frame buffer
 */
	{
	_LOG_L4C2(">>CMux0710Protocol::AddFrameFreeQ [aBpFrame=0x%x]",aBpFrame);

	iFreeFrameBufList.AddLast(*aBpFrame);

	if (iEnforcingFlowControl)
		{
		if (iFreeFrameCount >= KStartDataDlcsThreshold)
			{
			// Release flow control
			_LOG_L4C2("More than %d frames free",
				KStartDataDlcsThreshold);

			// re-enable a data dlc (note only re-enable one dlc at a time)
			iEnforcingFlowControl = iPortFactory.FindDlcToEnable();
			_LOG_L4C2("iEnforcingFlowControl=%d",iEnforcingFlowControl);
			}
		}

	iFreeFrameCount++;
	//MAF __ASSERT_DEBUG((iFreeFrameCount <= KMaxFreeFrames),PANIC(KPanicIllegalState));

	_LOG_L4C2("<<CMux0710Protocol::AddFrameFreeQ iFreeFrameCount=%d",
		iFreeFrameCount);
	}
	
TUint8 CMux0710Protocol::CalcFCS(TUint8* aBuffer, TInt aLen)
/**
 * This method calculates the checkSum for the specified buffer
 * with the specified length.
 *
 * @param aBuffer - Pointer to the data buffer
 * @param aLen    - Length of Number of bytes in the Buffer for which CheckSum to be calculated
 * @return checksum
 */
	{
    TUint8 frameCheckSum = 0xFF;
	aBuffer++;
	for (TInt i=0; i < aLen; i++ )
		{
		frameCheckSum = crctable[(frameCheckSum ^ (*aBuffer++))];
		}

	// One's Complement
	frameCheckSum = (TUint8) ((TUint8)(0xFF) - frameCheckSum);

	return frameCheckSum;
	}

TInt CMux0710Protocol::Create0710DataFrames(TDesC8& aMsgBuf, 
											   const TUint8 aDlcNum)
/**
 * This method is called by channel manager objects to fragment
 * a client message into frames for transmission to the BP.
 * The length of the client message is determined, the client message is
 * fragment into 27.010 format, and the formatted frames are added to the
 * write frame queue.
 *
 * @param aMsgBuf - Pointer to the client message
 * @param aDlcNum - DLC number
 * @return KErrNone, KErrArgument, or KErrNoMemory
 */
	{
	_LOG_L4C2(">>CMux0710Protocol::Create0710DataFrames [aDlcNum=%d]",
		aDlcNum);

	TInt ret = KErrNone;

	TInt msgLength   = aMsgBuf.Length();
	TInt offset      = 0;
	TInt frameLength = 0;
	TInt maxFrameLength = KMaxFrameSize;

	TBool beginFlag = ETrue;
	TBool endFlag = EFalse;

	_LOG_L4C2("msgLength = %d", msgLength);
	if (msgLength > 0)
		{
		while ((msgLength > 0)&&(ret == KErrNone))
			{
			CCsyMsgBufBpFrame* bpFrame = GetFreeFrameBuf();
			if (bpFrame)
				{
				// Set up the frame
				bpFrame->MsgDlc() = aDlcNum;

				if (msgLength > maxFrameLength)
					{
					_LOG_L4C3("Fragmenting (%d > %d)",msgLength,maxFrameLength);

					frameLength = maxFrameLength;
					bpFrame->CompleteWhenSent() = EFalse;
					}
				else
					{
					_LOG_L4C1("No Fragment");

					frameLength = msgLength;
					bpFrame->CompleteWhenSent() = ETrue;
					endFlag = ETrue;
					}
			
				// Test for convergence layer 4
				CPortC32InterfaceBase* port = 
					iPortFactory.FindPortC32Interface(aDlcNum);
				if (port)
					{
					if (port->GetClientType() == CPortFactory::EC32ClientIpNif)
						{
						_LOG_L4C1("Layer 4 frame");

						Create0710UIHLayer4FrameFromMsg(aMsgBuf, offset, 
							bpFrame, frameLength, aDlcNum, beginFlag, endFlag);

						// No longer the beginning
						beginFlag = EFalse;
						}
					else
						{
						_LOG_L4C1("Normal frame");

						Create0710UIHFrameFromMsg(
							aMsgBuf, offset, bpFrame, frameLength, aDlcNum);
						}

					_LOG_L4C1("Writing the frame");
					ret = iCommWriter->Write(bpFrame);
					}
				else
					{
					_LOG_L1C2("** No port defined for aDlcNum=%d",
						aDlcNum);
					}
				}
			else
				{
				// error no free frame available
				_LOG_L1C1("** No free frame buffer **");
				ret = KErrNoMemory;
				}

			msgLength -= frameLength;
			offset += maxFrameLength;
			}
		}
	else
		{
		ret = KErrArgument;
		}

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

void CMux0710Protocol::Create0710UIHFrameFromMsg(TDesC8& aMsgBuf,
												 TInt aOffset,
												 CCsyMsgBufBpFrame* aFrameBuf,
												 TInt aLength,
												 TUint8 aDlcNum)
/**
 * This method creates an 27.010 UIH frame from a message.
 * NOTE: This method assumes that a free frame buffer has been allocated.
 *
 * @param aMsgBuf - Pointer to a CSY memory element pointing to a Msg
 * @param aOffset - Offset from the start of the message to be copied to the frame.
 *                  This is needed if the calling method needs to defragment a long message.
 * @param aFrameBuf - Pointer to a CSY memory elelemt pointing to a Frame
 * @param aLength   - Length of the payload to be copied.
 * @param aDlcNum   - DLC channel number.
 */
    {
	_LOG_L4C3(">>CMux0710Protocol::Create0710UIHFrameFromMsg [aOffset=%d,aLength=%d]",aOffset,aLength);

	aFrameBuf->iMsg.Zero();

	// set initial length for headers
#ifdef _27010ADVANCEOPTION
	aFrameBuf->iMsg.SetLength(3);
#else
	aFrameBuf->iMsg.SetLength(4);
#endif

	// Octet 0 = Start Flag
	aFrameBuf->iMsg[0] = KCsy0710StartEndFlag;

	// Octet 1 = Non-extended Address, Command/Response, DLCI number
	aFrameBuf->iMsg[1] = (TUint8) ((aDlcNum << 2) | 0x03);  // Set the DLCI, EA, C/R

	// Octet 2 = Control Field = Frame Type (UIH)
	aFrameBuf->iMsg[2] = (TUint8) KCsy0710CTLUIH;
	

#ifdef _27010ADVANCEOPTION
	TInt checksumLength = 2;
#else
	// Octet 3 = Length indicator
	// ASSUME only 1 byte needed for length size
	//    27.010 supports 7 bits in Octet 3 to indicate a length up to 128 bytes long
	aFrameBuf->iMsg[3] = (TUint8) ((aLength << 1) | KCsy0710EA);


	// CRC Frame check : Basic Option  -> for Addr, Control, Length Fields only
	// length = 3 bytes  [Addr(1) + Control(1) + Length (1)]
	TInt checksumLength = 3;
#endif
	TUint8 checksum;
	checksum = (TUint8) CalcFCS(&aFrameBuf->iMsg[0], checksumLength);

	// Octet 5-x
	//CCsyMsgBufClient* csyMsgBufClient = STATIC_CAST(CCsyMsgBufClient*, aMsgBuf);
	const TUint8* temp = &aMsgBuf[aOffset];
	aFrameBuf->iMsg.Append(temp, aLength);
	TInt tempLength = aFrameBuf->iMsg.Length();
	aFrameBuf->iMsg.SetLength(tempLength + 2);
	aFrameBuf->iMsg[tempLength] = checksum;
	aFrameBuf->iMsg[tempLength+1] = KCsy0710StartEndFlag;

 	_LOG_L4C1("<<CMux0710Protocol::Create0710UIHFrameFromMsg");
	}

void CMux0710Protocol::Create0710UIHLayer4FrameFromMsg(TDesC8& aMsgBuf, 
													   TInt aOffset, 
													   CCsyMsgBufBpFrame* aFrameBuf, 
													   TInt aLength, 
													   TUint8 aDlcNum, 
													   TBool aLayer4Begin, 
													   TBool aLayer4End)
/**
 * This method creates an 27.010 UIH frame from a message.
 * NOTE: This method assumes that a free frame buffer has been allocated.
 *
 * @param aMsgBuf - Pointer to a CSY memory element pointing to a Msg
 * @param aOffset - Offset from the start of the message to be copied to the frame.
 *                  This is needed if the calling method needs to defragment a long message.
 *                  This method builds the message as a Convergence Layer 4 type, so
 *                  only Advanced Option.
 * @param aFrameBuf - Pointer to a CSY memory elelemt pointing to a Frame
 * @param aLength   - Length of the payload to be copied.
 * @param aDlcNum   - DLC channel number.
 * @param aLayer4Begin - Beginning of Convergence Layer 4.
 * @param aLayer4End   - End of Convergence Layer 4.
 */
    {
	_LOG_L4C3(">>CMux0710Protocol::Create0710UIHLayer4FrameFromMsg [aOffset=%d,aLength=%d]",aOffset,aLength);
	_LOG_L4C3("[aLayer4Begin=%d,aLayer4End=%d]",aLayer4Begin,aLayer4End);

	//aFrameBuf->iMsg.Zero(); - this is done in GetFreeFrameBuf

	// set initial length for headers
	aFrameBuf->iMsg.SetLength(3);

	// Octet 0 = Start Flag
	aFrameBuf->iMsg[0] = KCsy0710StartEndFlag;

	// Octet 1 = Non-extended Address, Command/Response, DLCI number
	aFrameBuf->iMsg[1] = (TUint8) ((aDlcNum << 2) | 0x03);  // Set the DLCI, EA, C/R

	// Octet 2 = Control Field = Frame Type (UIH)
	aFrameBuf->iMsg[2] = (TUint8) KCsy0710CTLUIH;

	TInt checksumLength = 2;
	TUint8 checksum;
	checksum = (TUint8) CalcFCS(&aFrameBuf->iMsg[0], checksumLength);

	// Octet 5-x	
	// Build the Convergence Layer 4 byte
	TUint8 tempLayer4Byte = 0x01;	// Default Middle Frame fragment 
	if (aLayer4Begin && aLayer4End)	// Begin and End - Single Frame Message
		{
		tempLayer4Byte = 0xC1; // MAF magic numbers
		}
	else if (aLayer4Begin)	// Begin Frame
		{
		tempLayer4Byte = 0x41;
		}
	else if (aLayer4End)	// End Frame
		{
		tempLayer4Byte = 0x81;
		}
	aFrameBuf->iMsg.Append(tempLayer4Byte);

	const TUint8* temp = &aMsgBuf[aOffset];
	aFrameBuf->iMsg.Append(temp, aLength);
	TInt tempLength = aFrameBuf->iMsg.Length();

	aFrameBuf->iMsg.SetLength(tempLength + 2);
	aFrameBuf->iMsg[tempLength] = checksum;
	aFrameBuf->iMsg[tempLength+1] = KCsy0710StartEndFlag;

	DumpFrame(aFrameBuf);

	_LOG_L4C1("<<CMux0710Protocol::Create0710UIHLayer4FrameFromMsg");
    }

TInt CMux0710Protocol::Create0710ControlFrame(TCsyFrameType aFrameType,
											  TUint8 aDlcNum,
											  TCsyCtrlCommand aType,
											  TUint8 aV24Signals)
/**
 * This method creates an 27.010 control frame using the specified frame type
 * and DLC number.
 * NOTE: This method assumes that a free frame buffer has been allocated.
 *
 * @param aFrameType - Frame type of the control frame
 * @param aDlcNum - DLC number of this frame
 * @return KErrNone or KErrGeneral
 */
	{
	_LOG_L4C2(">>CMux0710Protocol::Create0710ControlFrame [aDlcNum=%d]",aDlcNum);

	TInt ret = KErrNone;

	if (iMaxRetriesReached == EFalse)
		{
	
		#ifdef _27010ADVANCEOPTION
			TUint8 tempArray[15]; // MAF magic numbers
		#else
			TUint8 tempArray[8];
		#endif

		// Octet 0 = Start Flag
		tempArray[0] = KCsy0710StartEndFlag;

		// Octet 1 = Non-extended Address, initiating end (Command/Response), DLCI number
		tempArray[1] = (TUint8) ((aDlcNum << 2) | 0x03);  // Set the DLCI, EA, C/R

		// Octet 2 = Frame Type
		switch (aFrameType)
			{
		case ESABM:
			_LOG_L3C1("ESABM");
			tempArray[2] = (TUint8) KCsy0710CTLSABM;
			tempArray[2] |= KCsy0710PollFinal;
			break;
		case EUA:
			_LOG_L3C1("EUA");
			tempArray[1] = (TUint8) ((aDlcNum << 2) | 0x01);  // Set the DLCI, EA
			tempArray[2] = (TUint8) KCsy0710CTLUA;
			break;
		case EDM:
			_LOG_L3C1("EDM");
			tempArray[1] = (TUint8) ((aDlcNum << 2) | 0x01);  // Set the DLCI, EA
			tempArray[2] = (TUint8) KCsy0710CTLDM;
			break;
		case EDISC:
			_LOG_L3C1("EDISC");
			tempArray[2] = (TUint8) KCsy0710CTLDISC;
			tempArray[2] |= KCsy0710PollFinal;
			break;
		case EUIH:
			_LOG_L3C1("EUIH");
			tempArray[2] = (TUint8) KCsy0710CTLUIH;
			tempArray[2] |= KCsy0710PollFinal; // no pollbit
			break;
		case EUI:
			_LOG_L3C1("EUI");
			tempArray[2] = (TUint8) KCsy0710CTLUI;
			break;
		default:
			_LOG_L1C2("** Unknown FrameType=%d **",aFrameType);
			ret = KErrGeneral;
			break;
			}

	#ifndef _27010ADVANCEOPTION

		(void) aType;	//to hide warning.
		(void) aV24Signals; //to hide warning.

		// Octet 3 = Length1 indicator octet1
		tempArray[3] = (TUint8) 0x01;  // zero length and set EA bit

		// CRC Frame check : Basic Option  -> for Addr, Control, Length Fields only
		// length = 4 bytes  [Addr(1) + Control(1) + Length (2)]
		TInt length = 3;  
		tempArray[4] = (TUint8) CalcFCS(tempArray, length);
		tempArray[5] = KCsy0710StartEndFlag;

		// For this call of GetFreeFrameBuf do not check the low frame threshold
		// since control frame and it could be related to an already occurring flow
		// control action anyway.
		CCsyMsgBufBpFrame* ctrlFrame = GetFreeFrameBuf(EFalse);
		if (ctrlFrame)
			{
			ctrlFrame->iMsg.Copy(tempArray, 6);
			iCommWriter->Write(ctrlFrame); // MAF should be high priority frame
			}
	#else

		if (aFrameType == EUIH)
			{
			// Set the DLCI to 0
			tempArray[1]  = 0x03; // Set the DLCI to 0, EA, C/R
			}

		TUint8 checkSum; 
		TInt length = 2;
		checkSum = (TUint8) CalcFCS(tempArray, length);

		if (aFrameType == EUIH)
			{
			// Only two types of control UIH supported
			if (aType == EParamNeg)
				{
				_LOG_L3C1("Param Negotiate");

				tempArray[3]  = KCsy0710CTLUIH_DlcParamNegotiate;
				tempArray[4]  = 0x11; // i.e 8 bytes, EA
				tempArray[5]  = aDlcNum;
				tempArray[6]  = (KPNClBits << 4) + KPNFrameType;
				tempArray[7]  = KPNDlcPriority;
				tempArray[8]  = KPNAckTimer;
				tempArray[9]  = KPNMaxFrameSize & 0x00ff;
				tempArray[10] = KPNMaxFrameSize >> 8;
				tempArray[11] = KPNMaxRetransmissions;
				tempArray[12] = KPNWindowSize;
				tempArray[13] = checkSum;
				tempArray[14] = KCsy0710StartEndFlag;

				iParamNegotiateDlcNum = aDlcNum;
				}
			else
				{
				_LOG_L3C2("MSC aV24Signals=0x%x", aV24Signals);

				tempArray[3]  = KCsy0710CTLUIH_ModemStatusCmd;
				tempArray[4]  = 0x05; // i.e 2 bytes, EA
				tempArray[5]  = (TUint8) ((aDlcNum << 2) | 0x03);  // Set the DLCI, EA, 1
				tempArray[6]  = aV24Signals;
				tempArray[7] = checkSum;
				tempArray[8] = KCsy0710StartEndFlag;
				}
			}
		else
			{
			tempArray[3] = checkSum;
			tempArray[4] = KCsy0710StartEndFlag;
			}

		CCsyMsgBufBpFrame* ctrlFrame = GetFreeFrameBuf(EFalse);
		if (ctrlFrame)
			{
	#ifdef _27010ADVANCEOPTION
			if (aFrameType == EUIH)
				{
				if (aType == EParamNeg)
					{
					ctrlFrame->iMsg.Copy(tempArray, 15);
					}
				else
					{
					ctrlFrame->iMsg.Copy(tempArray, 9);
					}
				}
			else
				{
				ctrlFrame->iMsg.Copy(tempArray, 5);
				}
	#else
			ctrlFrame->iMsg.Copy(tempArray, 5);
	#endif

			_LOG_L3C1("Write the frame");
			iCommWriter->Write(ctrlFrame); // MAF should be high priority frame
			}
	#endif
		else
			{		// no memory available
			_LOG_L1C1("** No Memory Available **");
			ret = KErrNoMemory;
			}
		}
	else
		{	
		_LOG_L1C1("** Max Retries Reached **");
		ret = KErrTimedOut;
		}
	_LOG_L4C2("<<CMux0710Protocol::Create0710ControlFrame [ret=%d]",ret);
	return ret;
	}

TInt CMux0710Protocol::SwitchToMuxMode()
/**
 * This method is called to switch the baseband to multiplexer mode.
 * This method formats the AT command the buffer with the AT+CMUX command
 * and writes to the write FrameBuf List.
 *
 * @return KErrNone or KErrNoMemory
 */
	{
	_LOG_L4C1(">>CMux0710Protocol::SwitchToMuxMode");

#ifdef __CSY_PROTOTYPE__
	iMuxMgrState = ECsyMuxEnabled;
#else
	
	if(iMuxMgrState == ECsyWaitingForFlushResp)
		{
		//flush the read queue.
		iTimeouter->Start(KOneSecond);
		return KErrNone;
		}
	else
		{
		iTimeouter->Start(KTwoSeconds);
		}
		
	TInt ret = KErrNone;

	CCsyMsgBufBpFrame* initBuf = GetFreeFrameBuf();
	if (initBuf)
		{
		
#ifdef USE_TI_CONDAT_STACK
		if(iMuxMgrState == ECsyWaitingForResetResp)
			{
			//when using the TI stack we first attempt to reset the board using at%b.  
			_LOG_L3C1("Sending AT reset command");
			TBuf8<16> aBuf(KATCmdReset);
			initBuf->iMsg.Copy(aBuf);
			iMuxMgrState = ECsyWaitingForResetResp;
			}
		else if(iMuxMgrState == ECsyWaitingForSleepResp)
			{
			//Need to ensure that the TI stack will not timeout in the lull between commands
			_LOG_L3C1("Sending AT sleep command");
			TBuf8<16> aBuf(KATCmdSleep);
			initBuf->iMsg.Copy(aBuf);
			iMuxMgrState = ECsyWaitingForSleepResp;
			}
		else
			{
#endif
		_LOG_L3C1("Sending AT");
		TBuf8<16> aBuf(KATCmdAttention);
		initBuf->iMsg.Copy(aBuf);
		iMuxMgrState = ECsyWaitingForAttentionResp;

#ifdef USE_TI_CONDAT_STACK
			}
#endif
		iResponseStr.Zero();
		
		// call comm write to xmit frame
		// comm writer's RunL will run when frame has been xmitted by LDD
		// and return the frame buffer to the free list
		ret = iCommWriter->Write(initBuf);
		}
	else
		{
		_LOG_L1C1("** No Memory Available **");
		ret = KErrNoMemory;
		}
#endif

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

TInt CMux0710Protocol::ParseATResponse(TDes8& aResp)
/**
 * This method parses the specified AT ascii response for the
 * expected ascii "OK" string.  If the string is found then set
 * the Mux Mode to True.
 *
 * @param aResp - Reference to the AT response string to parse
 * @return KErrNone, KErrGeneral or KErrNotFound
 */
	{
	_LOG_L4C3(">>CMux0710Protocol::ParseATResponse [iMuxMgrState = %d, aResp=%S]",
		iMuxMgrState,&aResp);
		
	//Response string not always read in one go so concatonate it together to form full response string.
	TInt appendsize = iResponseStr.MaxSize() - iResponseStr.Length();
	iResponseStr.Append(aResp.LeftTPtr(appendsize));
	_LOG_L4C2("Result string concatenated = %S",&iResponseStr);
	
	if(iMuxMgrState == ECsyWaitingForFlushResp)
		{
		_LOG_L4C2("Flushed comm port on opening = %S",&iResponseStr);
		return KErrNotFound;
		}
		
#ifdef USE_TI_CONDAT_STACK
	if(iMuxMgrState == ECsyWaitingForResetResp)
		{
		if(iResponseStr.Find(KATInitialised) != KErrNotFound)
			{
			//got match - reset Rsp string to enter normal loop handle
			_LOG_L3C1("Board has successfully been reset.");
			iResponseStr = _L8("OK");
			iRetryCount = 0; // stop retries of the reset
			}
		}

	if(iMuxMgrState == ECsyWaitingForSleepResp)
		{
		if(iResponseStr.Find(_L8("OK")) != KErrNotFound)
			{
			//got match - sleep acknowledged
			_LOG_L3C1("Board has had sleep timeout disabled.");
			iRetryCount = 0; //stop retries of the sleep;
			}
		}				
#endif

	TInt ret = KErrNone;

	// all AT responses should contain an "OK" keyword
	if ((iResponseStr.Find(_L8("OK")) != KErrNotFound) ||
		(iResponseStr.Find(_L8("ERROR")) != KErrNotFound))
		{
		if (iResponseStr.Find(_L8("ERROR")) != KErrNotFound)
			{
#ifdef USE_TI_CONDAT_STACK
			if(iMuxMgrState == ECsyWaitingForResetResp)
				{
				_LOG_L3C1("*******TI Board failed to reset (AT%b) - continue anyway as may already be in a stable state.*******");
				iRetryCount--;
				}
			else if (iMuxMgrState == ECsyWaitingForSleepResp)
				{
				_LOG_L3C1("*******TI Board failed to acknowledge sleep disable (AT%SLEEP=0) - continue anyway as may already be in a stable state.*******");
				iRetryCount--;
				}
			else
				{
				_LOG_L3C1("****************** Received ERROR back ****************");
				}
#else
			_LOG_L3C1("****************** Received ERROR back ****************");
#endif
			}
		iTimeouter->Stop();

		switch (iMuxMgrState)
			{
#ifdef USE_TI_CONDAT_STACK
		case ECsyWaitingForResetResp:
			{			
			_LOG_L3C1("ECsyWaitingForResetResp - Start proper init sequence.");
			if(iRetryCount>0) 
				iMuxMgrState = ECsyWaitingForResetResp; //try reset command again
			else
				{
				iMuxMgrState = ECsyWaitingForSleepResp;
				iRetryCount = KRetryCount;
				}				
			SwitchToMuxMode();
			}
			break;
			
		case ECsyWaitingForSleepResp:
			{			
			iResponseStr.Zero();
			_LOG_L3C1("ECsyWaitingForSleepResp");
			if(iRetryCount>0)
				iMuxMgrState = ECsyWaitingForSleepResp;
			else
				iMuxMgrState = ECsyWaitingForAttentionResp;
			SwitchToMuxMode();
			}
			break;			
#endif			
		case ECsyWaitingForAttentionResp:
			{
			iResponseStr.Zero();
			CCsyMsgBufBpFrame* atCmdBuf = GetFreeFrameBuf();
			if (atCmdBuf)
				{
				_LOG_L3C1("Writing ATE0 command");
				atCmdBuf->iMsg.Copy(KATCmdDisableEcho);
				iCommWriter->Write(atCmdBuf);
				iMuxMgrState = ECsyWaitingForEchoDisableResp;
				}

			iTimeouter->Start(KTwoSeconds);
			}
			break;

		case ECsyWaitingForEchoDisableResp:
			{
			iResponseStr.Zero();
			CCsyMsgBufBpFrame* atCmdBuf = GetFreeFrameBuf();
			if (atCmdBuf)
				{
				_LOG_L3C1("Writing CMUX cmd");
				atCmdBuf->iMsg.Copy(KCsyDefaultATEnterMuxModeCmd);
				iCommWriter->Write(atCmdBuf);
				iMuxMgrState = ECsyWaitingForCmuxResp;
				}

			iTimeouter->Start(KTwoSeconds);
			}
			break;

		case ECsyWaitingForCmuxResp:
			{
			iResponseStr.Zero();
			_LOG_L3C1("Got CMUX response");
			iMuxMgrState = ECsyMuxEnabled;

			// start the connect process for the control, command & data channels
			iPortFactory.ConnectControlChannel();
			}
			break;

		default:
			_LOG_L3C2("** Invalid Mux Mgr State = %d **", iMuxMgrState);
			ret = KErrGeneral;
			break;
			}
		}
	else
		{
		ret = KErrNotFound;
		}

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

void CMux0710Protocol::TimedOut()
/**
 * This resends the AT command required.
 */
	{
	_LOG_L4C2(">>CMux0710Protocol::TimedOut [iMuxMgrState=%d]",iMuxMgrState);

	switch (iMuxMgrState)
		{

	case ECsyWaitingForFlushResp:
		{
		//read queue has just been flushed, now start switch to MUX mode
		_LOG_L3C1("ECsyWaitingForFlushResp");
#ifdef USE_TI_CONDAT_STACK
		iMuxMgrState = ECsyWaitingForResetResp;
#else
		iMuxMgrState = ECsyWaitingForAttentionResp;
#endif
		SwitchToMuxMode();
		}
		break;
#ifdef USE_TI_CONDAT_STACK
	case ECsyWaitingForResetResp:
		{
		_LOG_L3C1("ECsyWaitingForResetResp");
		if(--iRetryCount>0) 
			iMuxMgrState = ECsyWaitingForResetResp; //try reset command again
		else
			iMuxMgrState = ECsyWaitingForSleepResp;	
		SwitchToMuxMode();
		}
		break;

	case ECsyWaitingForSleepResp:
		{
		_LOG_L3C1("ECsyWaitingForSleepResp");
		if(--iRetryCount>0)
			iMuxMgrState = ECsyWaitingForSleepResp; //try sleep command again
		else
			iMuxMgrState = ECsyWaitingForAttentionResp;
		SwitchToMuxMode();	
		}
		break;
#endif
	case ECsyWaitingForAttentionResp:
		{
		if (++iAtResponseTimeout < KAtResponseTimeoutLimit)
			{
			_LOG_L3C2("ECsyWaitingForAttentionResp [timeout:%d]",iAtResponseTimeout);
			SwitchToMuxMode();	
			}
		else
			{
			_LOG_L3C2("Max retries [%d] reached for At Response", KAtResponseTimeoutLimit);

			iMaxRetriesReached = ETrue;
			//call to scheduler DoCancel required here
			iPortFactory.ChannelCtrlDoCancel();
			}
		}
		break;

	case ECsyWaitingForEchoDisableResp:
		{
		_LOG_L3C1("ECsyWaitingForEchoDisableResp");
		iResponseStr.Zero();
		CCsyMsgBufBpFrame* atCmdBuf = NULL;
		atCmdBuf = GetFreeFrameBuf();
		if (atCmdBuf)
			{
			TBuf8<16> tempBuf(KATCmdDisableEcho);
			atCmdBuf->iMsg.Copy(tempBuf);
			iCommWriter->Write(atCmdBuf);
			}

		iTimeouter->Start(KOneSecond);
		}
		break;

	case ECsyWaitingForCmuxResp:
		{
		_LOG_L3C1("ECsyWaitingForCmuxResp");
		iResponseStr.Zero();
		CCsyMsgBufBpFrame* atCmdBuf = GetFreeFrameBuf();
		if (atCmdBuf)
			{
			_LOG_L3C1("Writing CMUX cmd");
			atCmdBuf->iMsg.Copy(KCsyDefaultATEnterMuxModeCmd);
			iCommWriter->Write(atCmdBuf);
			iMuxMgrState = ECsyWaitingForCmuxResp;
			}
		iTimeouter->Start(KTwoSeconds);
		}
		break;

	default:
		_LOG_L1C2("** Invalid Mux Mgr State = %d **", iMuxMgrState);
		break;
		}

	_LOG_L4C1("<<CMux0710Protocol::TimedOut");
	}

void CMux0710Protocol::DumpFrame(CCsyMsgBufBpFrame* aFrameBuf)
/**
 * Logs the packet into the log file.
 *
 * @param aPacket The incoming packet
 */
	{
	_LOG_L4C1(">>CMux0710Protocol::DumpFrame");

	TInt packetLen = aFrameBuf->iMsg.Length();
	_LOG_L4C2("frame length %d",packetLen);

	TBuf8<256> logBuf;
	TBuf8<256> logBuf2;

	logBuf.Copy(_L8("    "));
	logBuf2.Copy(_L8(" "));
	_LOG_L4C1("");

	for (TInt i = 0; i <= packetLen; i++)
		{
		if (i >= packetLen)
			{
			logBuf.Append(logBuf2);
			_LOG_L4C2("%S",&logBuf);
			break;
			}
		if (((i % 16) == 0) && (i > 0))
			{
			logBuf.Append(logBuf2);
			_LOG_L4C2("%S",&logBuf);
			logBuf.Copy(_L8("    "));
			logBuf2.Copy(_L8(" "));
			}
		logBuf.AppendFormat(_L8("%02X "), aFrameBuf->iMsg[i]);
		if (TChar(aFrameBuf->iMsg[i]).IsPrint())
			logBuf2.AppendFormat(_L8("%c"), aFrameBuf->iMsg[i]);
		else
			logBuf2.Append(_L8("."));
		}

	_LOG_L4C1("<<CMux0710Protocol::DumpFrame");
	_LOG_L4C1("");
	}