diff -r 2473f5e227f9 -r 8b72faa1200f cbsref/csyrefplugins/csy27010/src/PortC32InterfaceIp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cbsref/csyrefplugins/csy27010/src/PortC32InterfaceIp.cpp Tue Jun 22 11:02:32 2010 +0100 @@ -0,0 +1,670 @@ +// +// * 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 CPortC32Interface class. +// * This class contains methods which are invoked by C32 when the +// * associated client RComm public API is invoked. These methods +// * are used to create, configure, read, write, and close logical +// * serial ports. Instances of this class are created by the CSY's +// * Port Factory. +// + +/** @file PortC32InterfaceIp.cpp + * + * This file contains the implementation for the CPortC32InterfaceIp class. + * This class contains methods which are invoked by C32 when the + * associated client RComm public API is invoked. These methods + * are used to create, configure, read, write, and close logical + * serial ports. Instances of this class are created by the CSY's + * Port Factory. + * + */ + +#include +#include "PortC32InterfaceIp.h" +#include "Portfactory.h" +#include "Mux0710Protocol.h" +#include "CsyMsgBufBPFrame.h" +#include "ChannelMgrCmdData.h" +#include "CommFrameReaderAo.h" +#include "CsyDebugLogger.h" +#include "CsyGlobals.h" +#include "CommFrameWriterAo.h" + +CPortC32InterfaceIp* CPortC32InterfaceIp::NewL(CPortFactory& aPortFactory, + CPortFactory::TC32PortInfo& aPortInfo) +/** + * This method uses two phase construction and the cleanup stack to create + * an instance of class CPortC32InterfaceIp. + * + * @param aPortFactory - Reference to the port factory + * @param aPortInfo - Reference to the port information + * @return Pointer to the created instance + */ + { + _LOG_L4C1("CPortC32InterfaceIp::NewL"); + + CPortC32InterfaceIp* self = + new(ELeave) CPortC32InterfaceIp(aPortFactory, aPortInfo); + + TCleanupItem closeSelf(CPortFactory::CloseObject, self); + CleanupStack::PushL(closeSelf); + self->ConstructL(); + CleanupStack::Pop(self); + + return (self); + } + +CPortC32InterfaceIp::~CPortC32InterfaceIp() +/** + * Destructor. + */ + { + _LOG_L4C1(">>CPortC32InterfaceIp::~CPortC32InterfaceIp"); + + _LOG_L3C1("Remove port from the port factory"); + + // let port factory know we are deleted + iPortFactory.RemoveC32Port(this); + CompleteOutstandingRequest(); + + _LOG_L3C1("Release any packets going to the C32 client"); + + // remove all frames to do with the most recent IP packet + CCsyMsgBufBpFrame* ipPacketFrame = NULL; + iFramesReceivedForIpPacketIter.SetToFirst(); + while ((ipPacketFrame = iFramesReceivedForIpPacketIter++) != NULL) + { + iFramesReceivedForIpPacket.Remove(*ipPacketFrame); + delete ipPacketFrame; + } + + _LOG_L4C1("<>CPortC32InterfaceIp::ConstructL"); + + CPortC32InterfaceBase::ConstructL(); + + _LOG_L4C1("<>CPortC32InterfaceIp::ResetBuffers [aFlags=%d,port=%d]", + aFlags,GetPortNumber()); + + if (aFlags & KCommResetRx) + { + _LOG_L4C1("Removing all messages intended for the C32 client"); + + RemoveWaitingAllFrames(); + + // remove all frames to do with the most recent IP packet + CCsyMsgBufBpFrame* ipPacketFrame = NULL; + iFramesReceivedForIpPacketIter.SetToFirst(); + while ((ipPacketFrame = iFramesReceivedForIpPacketIter++) != NULL) + { + iFramesReceivedForIpPacket.Remove(*ipPacketFrame); + delete ipPacketFrame; + } + } + + if (aFlags & KCommResetTx) + { + _LOG_L4C1("Removing all messages intended for the modem"); + + GetMuxChannel()->WriteCancel(); + } + + _LOG_L4C1("<>CPortC32InterfaceIp::PlaceIpPacketFramesOntoFreeList [port=%d]", GetPortNumber()); + + CCsyMsgBufBpFrame* frame = NULL; + iFramesReceivedForIpPacketIter.SetToFirst(); + while ((frame = iFramesReceivedForIpPacketIter++) != NULL) + { + iFramesReceivedForIpPacket.Remove(*frame); + iPortFactory.GetMux0710Protocol()->AddFrameFreeQ(frame); + } + iCurrentIpPacketLength = 0; + + _LOG_L4C1("<>CPortC32InterfaceIp::PlaceIpPacketFramesOntoReadList [port=%d]", GetPortNumber()); + + CCsyMsgBufBpFrame* frame = NULL; + iFramesReceivedForIpPacketIter.SetToFirst(); + while ((frame = iFramesReceivedForIpPacketIter++) != NULL) + { + iFramesReceivedForIpPacket.Remove(*frame); + iFramesWaitingToBeReadList.AddLast(*frame); + } + iCurrentIpPacketLength = 0; + iNumberOfPacketsWaiting++; + _LOG_L4C2("iNumberOfPacketsWaiting=%d",iNumberOfPacketsWaiting); + + if (iNumberOfPacketsWaiting == KMaxPacketsOutstandingForC32Client) + { + _LOG_L2C1("Client appears to be slow at reading"); + _LOG_L2C3("iNumberOfPacketsWaiting %d > KMaxPacketsOutstandingForC32Client %d)", + iNumberOfPacketsWaiting,KMaxPacketsOutstandingForC32Client); + + iMuxChannel->SetCsyToModemFlowControl(EFlowControlOn); + } + + _LOG_L4C1("<>CPortC32InterfaceIp::SendFrameToClient [port=%d]", GetPortNumber()); + + if (aFrame) + { + // frame validation + if (aFrame->iMsg.Length() <= KAdvOptionNumOfNonDataOctets) + { + _LOG_L1C1("** Does not appear to be a valid frame - disregarding **"); + + // Place received frames on the empty list + iPortFactory.GetMux0710Protocol()->AddFrameFreeQ(aFrame); + PlaceIpPacketFramesOntoFreeList(); + + _LOG_L4C1("<GetType4FrameSequence(); + _LOG_L4C2("framePosition = 0x%02x",framePosition); + + // read buffer validation + if (iFramesReceivedForIpPacket.IsEmpty()) + { + // There is no read buffer allocated for this frame + switch (framePosition) + { + case KSingleFrame: + case KStartMultiFrame: + { + _LOG_L4C1("Starting new IP frame list"); + iCurrentIpPacketLength = 0; + } + break; + case KEndMultiFrame: + case KMiddleMultiFrame: + default: + // assumption here is that because no read buffer is allocated then + // there cannot have been a valid start frame + _LOG_L1C1("** Missed start of packet - disregarding **"); + + // Place received frame on the empty list + iPortFactory.GetMux0710Protocol()->AddFrameFreeQ(aFrame); + + _LOG_L4C1("<iMsg.Length() - KAdvOptionNumOfNonDataOctets; + _LOG_L4C2("length=%d",length); + + // length validation + if ((iCurrentIpPacketLength + length) > KMaxIpPacketSize) + { + // The length of the data in the new frame would exceed that available + // in the read buffer. + + _LOG_L1C3("** iCurrentIpPacketLength + length %d exceeds max size %d **", + (iCurrentIpPacketLength + length),KMaxIpPacketSize); + + // Place received frames on the empty list + iPortFactory.GetMux0710Protocol()->AddFrameFreeQ(aFrame); + PlaceIpPacketFramesOntoFreeList(); + + _LOG_L4C1("<AddFrameFreeQ(aFrame); + PlaceIpPacketFramesOntoFreeList(); + + _LOG_L4C1("<>CPortC32InterfaceIp::CreateIpPacketFromFrames [port=%d]", GetPortNumber()); + + iIpPacket.Zero(); + + TUint8 framePosition = 0; + TInt length = 0; + TBool packetRetrieved = EFalse; + + // Remove all frames to do with the same IP Packet from waiting to be read list + CCsyMsgBufBpFrame* frame = NULL; + iFramesWaitingToBeReadIter.SetToFirst(); + while ((frame = iFramesWaitingToBeReadIter++) != NULL) + { + iFramesWaitingToBeReadList.Remove(*frame); + + framePosition = frame->GetType4FrameSequence(); + _LOG_L4C2("framePosition = 0x%02x",framePosition); + + length = frame->iMsg.Length() - KAdvOptionNumOfNonDataOctets; + _LOG_L4C2("length=%d",length); + + iIpPacket.Append(&frame->iMsg[KAdvOptionType4StartOfMessageData], length); + + iPortFactory.GetMux0710Protocol()->AddFrameFreeQ(frame); + + if ((framePosition == KSingleFrame)||(framePosition == KEndMultiFrame)) + { + _LOG_L4C1("retrieved packet"); + packetRetrieved = ETrue; + + if (iNumberOfPacketsWaiting == KMaxPacketsOutstandingForC32Client) + { + _LOG_L2C1("Client appears to be reading again"); + + // Assume it is okay to set FC to Off even in low free frame + // condition since just freed a frame. + + iMuxChannel->SetCsyToModemFlowControl(EFlowControlOff); + } + + iNumberOfPacketsWaiting--; + _LOG_L4C2("iNumberOfPacketsWaiting=%d",iNumberOfPacketsWaiting); + break; + } + } + + _LOG_L4C2("<>CPortC32InterfaceIp::ReadFromBufOrQueue [port=%d]", GetPortNumber()); + + TBool completedRead = EFalse; + TInt ret = KErrNone; + + _LOG_L4C2("iOneOrMore=%d",iOneOrMore); + _LOG_L4C2("iClientLength=%d",iClientLength); + + while ((CreateIpPacketFromFrames())&&(!ret)) + { + TInt ipPacketLength = iIpPacket.Length(); + TInt length = -1; + if (iClientLength - iPos < ipPacketLength) + { + length = iClientLength - iPos; + _LOG_L4C2("length remaining = %d",length); + } + + if ((length > -1) && (ipPacketLength >= length)) + { + // MAF should partial reads be allowed? + _LOG_L2C1("Partial read?"); + + } + else + { + _LOG_L4C3("read buf %d >= length %d ", ipPacketLength, length); + + ret = IPCWrite(iClientBuffer, iIpPacket, iPos); + if (ret) + { + _LOG_L1C2("** IPCWrite Error %d **",ret); + } + + _LOG_L4C3("Read: iPos = %d, add %d bytes", iPos, ipPacketLength); + + iPos += ipPacketLength; + } + } + + if (iPos>0) + { + if (iOneOrMore) + { + CompleteReadRequest(ret); + + iPos = 0; + completedRead = ETrue; + } + else + { + //normal read? and have not filled the buffer yet + _LOG_L4C3( "Not filled buffer yet iPos = %d, iClientLength = %d", iPos, iClientLength); + } + } + + _LOG_L4C2("<>CPortC32InterfaceIp::ReadFromBufOrQueue [port=%d]", GetPortNumber()); + + TBool completedRead = EFalse; + TInt err = KErrGeneral; + TBool cont; + do + { + cont = EFalse; + if(iQueuedIpPacket == NULL) + { + //Read data from the frame list + if (!iMsgToClientList.IsEmpty()) + { + _LOG_L4C1("Set to first item"); + iQueuedIpPacket = iMsgToClientList.First(); + if (iQueuedIpPacket) + { + _LOG_L4C1("iQueuedIpPacket not null"); + // remove msg buf from client list + iMsgToClientList.Remove(*iQueuedIpPacket); + } + } + } + if (iQueuedIpPacket) + { + TInt length = KErrNotFound; // <- yeaks! + if (iClientLength - iPos < iQueuedIpPacket->iMsg.Length()) + { + length = iClientLength - iPos; + _LOG_L4C2("length remaining = %d",length); + } + + if (iConfig.iTerminatorCount > 0) + { + _LOG_L4C2("iTerminatorCount = %d",iConfig.iTerminatorCount); + + // First find terminator + TInt terminatorLoc = KErrNotFound; // <- yeaks! + TInt loc; + for (TInt i = 0; i < iConfig.iTerminatorCount; i++) + { + loc = iQueuedIpPacket->iMsg.LocateF(iConfig.iTerminator[i]); + if (loc > KErrNotFound) + { + if (terminatorLoc == KErrNotFound) + { + terminatorLoc = loc; + } + else + { + terminatorLoc = Min(loc,terminatorLoc); + } + } + } + if (terminatorLoc > KErrNotFound) + { + if (length > KErrNotFound) + length = Min(terminatorLoc + 1,length); + else + length = terminatorLoc + 1; + } + _LOG_L4C2("length = %d",length); + } + + _LOG_L4C2("Read buf length %d",iQueuedIpPacket->iMsg.Length()); + + if ((iQueuedIpPacket->iMsg.Length() >= length) && (length > KErrNotFound)) + { + LOGTEXT2(__DEBUGLEVELMAJOR__,"complete partial read: # %d ", length); + + iPartialReadBuf.Copy(&iQueuedIpPacket->iMsg[0], length); + iQueuedIpPacket->iMsg.Delete(0, length); + + err = IPCWrite(iClientBuffer, iPartialReadBuf, iPos); + if (err) + { + _LOG_L1C2("** IPCWrite Error %d **",err); + } + + CompleteReadRequest(err); + err = KErrGeneral; + + completedRead = ETrue; + iPos = 0; + + if (iQueuedIpPacket->iMsg.Length() == 0) + { + _LOG_L4C1("All data used - freeing read buffer"); + AddToFreeC32BufferQ(iQueuedIpPacket); + iQueuedIpPacket = NULL; + } + } + else + { + LOGTEXT3(__DEBUGLEVELMAJOR__,"read buf %d >= length %d ", iQueuedIpPacket->iMsg.Length(), length); + + err = IPCWrite(iClientBuffer, iQueuedIpPacket->iMsg, iPos); + + _LOG_L4C3("Read: iPos = %d, add %d bytes", iPos, iQueuedIpPacket->iMsg.Length()); + + cont = ETrue; //try read next frame in the list + iPos = iPos + iQueuedIpPacket->iMsg.Length(); + + _LOG_L4C1("Freeing read buffer"); + AddToFreeC32BufferQ(iQueuedIpPacket); + iQueuedIpPacket = NULL; + } + } + } + while (cont); + + if (iPos>0) + { + if (iOneOrMore) + { + if (err) + { + _LOG_L1C2("** IPCWrite Error %d **",err); + } + + CompleteReadRequest(err); + + iPos = 0; + completedRead = ETrue; + } + else + { + //normal read and have not filled the buffer yet + _LOG_L4C3( "Not filled buffer yet iPos = %d, iClientLength = %d", iPos, iClientLength); + //iToClientMsgQAo->IssueNotificationRequest(); + } + } + + _LOG_L4C2("<