diff -r 2473f5e227f9 -r 8b72faa1200f cbsref/csyrefplugins/csy27010/src/ChannelMgrBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cbsref/csyrefplugins/csy27010/src/ChannelMgrBase.cpp Tue Jun 22 11:02:32 2010 +0100 @@ -0,0 +1,818 @@ +// +// * 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: The CChannelMgrBase class defines a single 3GPP 27.010 based logical channel +// * called DLC. This base class is inherited by derived control and data channel +// * classes which add specific channel type behavior. +// + +// ChannelMgrBase.cpp + +/** @file ChannelMgrBase.cpp + * + */ + +#include "ChannelMgrBase.h" +#include "CsyMsgBufBpFrame.h" +#include "PortC32Interface.h" +#include "Mux0710Protocol.h" +#include "CsyDebugLogger.h" +#include "CommFrameWriterAo.h" + +CChannelMgrBase::CChannelMgrBase(const TUint8 aDlcNum, + CPortFactory& aPortFactory, + CMux0710Protocol& aMux0710Protocol) +: iV24Signals(0x0D), + iDlcNum(aDlcNum), +#ifndef __CSY_PROTOTYPE__ + iChannelState(ECsyChannelStateDisconnected), +#else + iChannelState(ECsyChannelStateConnected), +#endif + iPortFactory(aPortFactory), + iPortC32Interface(NULL), +#ifndef __CSY_PROTOTYPE__ + iMux0710Protocol(aMux0710Protocol), +#else + iMux0710Protocol(aMux0710Protocol), + iChannelReady(ETrue), + iInitFinished(ETrue), +#endif + iModemAllowedToSendFrames(EFlowControlOff) +/** + * Constructor. + * @param aDlcNum - DLC number for the channel + * @param aPortFactory - Reference to port factory + * @param aMux0710Protocol - Reference to the Mux 27.010 object + */ + { + } + +CChannelMgrBase::~CChannelMgrBase() +/** + * Destructor. Delete all resources and memory allocated by this object. + */ + { + _LOG_L4C1("CChannelMgrBase::~CChannelMgrBase"); + + delete iChannelObserverAo; + delete iTimeouter; + } + +void CChannelMgrBase::ConstructL() +/** + * Create any instances and allocate any memory used by this object. + */ + { + _LOG_L4C1("CChannelMgrBase::ConstructL"); + + iChannelObserverAo = CChannelObserverAo::NewL(); + CActiveScheduler::Add(iChannelObserverAo); + + iTimeouter = CActiveTimeouter::NewL(*this); + iTimeoutVal = KOneSecond; + iTxCountLimit = 10; + } + +TDes8& CChannelMgrBase::RefToMsgBuffer() +/** + * This method returns a pointer to the message buffer to use + * to format a message to send to the baseband. + * + * @return pointer + */ + { + // only one buffer is available for messages to the baseband + return iDataToSendToModem; + } + +void CChannelMgrBase::ProcessRecvFrame(CCsyMsgBufBpFrame* aBpFrame) +/** + * This method is called to process a frame that was received + * + * @param aBpFrame - Pointer to the frame buffer + */ + { + if (aBpFrame->GetFrameType() != KCsy0710CTLUIH) + ProcessNonUihRecvFrame(aBpFrame); + else + ProcessRecvUihFrame(aBpFrame); + } + +TInt CChannelMgrBase::PlaceOnOutboundQueue() +/** + * This method is called to process the "to baseband Message Q" event + * for the channel. This event indicates that there is a message + * that needs to be sent to the baseband. + */ + { + _LOG_L4C2(">>CChannelMgrBase::PlaceOnOutboundQueue [iDlcNum=%d]",iDlcNum); + + TInt ret = KErrNone; + + if (iCsyAllowedToSendFrames == EFlowControlOn) + { + _LOG_L4C1("Csy -> modem flow control = ON"); + iDelayedWriteToModem = ETrue; + + // We cannot fragment and place it on the write queue yet since + // flow control in the direction of Csy to modem is set to ON. + + _LOG_L4C1("<>CChannelMgrBase::WriteCancel"); + + if (iDelayedWriteToModem) + { + _LOG_L4C1("Delayed write has been cancelled"); + iDelayedWriteToModem = EFalse; + } + + _LOG_L4C1("Remove any frames on write queue"); + + // remove any frames (if any exist) from the writer Ao and + // place them on the free queue + + CCommFrameWriterAo* writer = iPortFactory.GetCommWriterAo(); + + writer->RemoveAnyDlcFramesOnWriteList(iDlcNum, EFalse); + writer->RemoveAnyDlcFramesFromWaitList(iDlcNum, EFalse); + + _LOG_L4C1("<>CChannelMgrBase::Connect [iDlcNum=%d,iChannelState=%d]", + iDlcNum,iChannelState); + + TInt ret = KErrNone; + if (iChannelState != ECsyChannelStateConnected) + { + _LOG_L4C1("Dlc is not currently connected"); + ret = iMux0710Protocol.Create0710ControlFrame(CMux0710Protocol::ESABM, iDlcNum); + if (ret == KErrNone) + { + iChannelState = ECsyChannelStateConnecting; + iInitFinished = EFalse; + iTimeouter->Stop(); + iTimeouter->Start(iTimeoutVal); + iTxCount = iTxCountLimit; + } + else + { + _LOG_L1C1("** Cannot send SABM **"); + } + } + else + { + _LOG_L2C1("** Ignored Connect **"); + ret = KErrGeneral; + } + + _LOG_L4C2("<>CChannelMgrBase::ParameterNegotiate [iDlcNum=%d,iChannelState=%d]", + iDlcNum,iChannelState); + + TInt ret = KErrNone; + if (iChannelState != ECsyChannelStateConnected) + { + _LOG_L4C1("Dlc is not currently connected"); + if (iMux0710Protocol.Create0710ControlFrame(CMux0710Protocol::EUIH, iDlcNum) == KErrNone) + { + iChannelState = ECsyChannelStateParameterNegotiating; + iTimeouter->Stop(); + iTimeouter->Start(iTimeoutVal); + iTxCount = iTxCountLimit; + } + else + { + _LOG_L1C1("** Cannot send EUIH Param Neg. **"); + ret = KErrGeneral; + } + } + else + { + _LOG_L2C1("** Ignored ParameterNegotiate **"); + } + + _LOG_L4C2("<>CChannelMgrBase::Disconnect [iDlcNum=%d,iChannelState=%d]", + iDlcNum,iChannelState); + + TInt ret = KErrNone; + if (iChannelState == ECsyChannelStateConnected) + { + _LOG_L4C1("Dlc is currently connected"); + if (iMux0710Protocol.Create0710ControlFrame(CMux0710Protocol::EDISC, iDlcNum) == KErrNone) + { + iChannelState = ECsyChannelStateDisconnecting; + _LOG_L1C2("** Setting Channel Ready to False for DLC %d **",iDlcNum); + iChannelReady = EFalse; + iTimeouter->Stop(); + + // Allow time for the channel to disconnect... + User::After(1); + } + else + { + _LOG_L1C1("** Cannot send EDISC **"); + ret = KErrGeneral; + } + } + else if (iChannelState == ECsyChannelStateTransmitError) + { + _LOG_L2C1("** Disconnect request for channel with transmit error **"); + ret = KErrNone; + } + else + { + _LOG_L2C1("** Ignored disconnect **"); + ret = KErrGeneral; + } + + _LOG_L4C2("<>CChannelMgrBase::ProcessNonUihRecvFrame [iDlcNum=%d]", iDlcNum); + + TUint8 frameType = aBpFrame->GetFrameType(); + iMux0710Protocol.AddFrameFreeQ(aBpFrame); + + switch (frameType) + { + case KCsy0710CTLSABM: + _LOG_L4C1("SABM"); + // MAF we should respond to this + break; + + case KCsy0710CTLUA: + { + _LOG_L4C1("UA"); + iTimeouter->Stop(); + + if (iChannelState == ECsyChannelStateConnecting) + { + _LOG_L4C1("SABM received by remote end - send MSC command"); + if (SendMscCommand(iV24Signals) == KErrNone) + iChannelState = ECsyChannelStateMSCsent; + } + else if (iChannelState == ECsyChannelStateDisconnecting) + { + _LOG_L4C2("Channel disconnected %d", iDlcNum); + iChannelState = ECsyChannelStateDisconnected; + + if (iPortFactory.DecrementNumOfOpenPorts()) + { + NotifyChannelReady(); + } + } + } + break; + + case KCsy0710CTLDM: // 0x0F + _LOG_L4C1("DM"); + break; + + case KCsy0710CTLDISC: // 0x43 + _LOG_L4C1("DISC"); + // MAF we should respond to this + break; + + case KCsy0710CTLUIH: + case KCsy0710CTLUI: + // MAF __ASSERT_DEBUG(EFalse,PANIC(KPanicIllegalState)); here + break; + + default: + _LOG_L1C2("** Unknown FrameType = 0x%02x **", frameType); + break; + } + + _LOG_L4C1("<>CChannelMgrBase::SendMscCommand [aV24Signals=0x%02x]", + aV24Signals); + + if (iMscReplyExpected) + { + _LOG_L4C1("<Stop(); + iTimeouter->Start(iTimeoutVal); + iTxCount = iTxCountLimit; + iMscReplyExpected = ETrue; + } + + _LOG_L4C2("<>CChannelMgrBase::MscReceived [aV24Signals=0x%x]", + aV24Signals); + + if (!iMscReplyExpected) + { + _LOG_L2C1("*** Not expecting MscReceived? ***"); + return; + } + + iMscReplyExpected = EFalse; + iTimeouter->Stop(); + + if (iChannelState == ECsyChannelStateMSCsent) + { + _LOG_L4C1("MSC cmd part of start up sequence"); + iChannelState = ECsyChannelStateWaitingForChannelReady; + + //different type of channel may need different init process. + if (iPortC32Interface) + { +#ifdef _27010ADVANCEOPTION + if (iPortC32Interface->GetClientType() == CPortFactory::EC32ClientIpNif) + { + _LOG_L4C1(" IpNif Channel Initialized"); + // Don't need to wait for AT command interpreter ready since not AT + iChannelState = ECsyChannelStateConnected; + NotifyChannelReady(); + ModemAndCsyToClientFlowCtrl(EFlowControlOff); + } +#endif + } + else + { + // Command channel + iChannelState = ECsyChannelStateConnected; + NotifyChannelReady(); + } + } + + if ((iDlcNum)&&(iV24Signals != aV24Signals)) + { + _LOG_L4C3("Data Dlc - Response different to sent [%x != %x]", + iV24Signals, aV24Signals); + + ReceivedV24Signals(aV24Signals); + } + + _LOG_L4C1("<>CChannelMgrBase::ModemAndCsyToClientFlowCtrl [aFlowControl=%d,iDlcNum=%d]", + aFlowControl,iDlcNum); + + iCsyAllowedToSendFrames = aFlowControl; + if ((aFlowControl == EFlowControlOff)&&(iDelayedWriteToModem)) + { + _LOG_L4C1("Flow control now OFF - delayed frame to send"); + + TInt ret = iMux0710Protocol.Create0710DataFrames(iDataToSendToModem, iDlcNum); + if (ret) + { + _LOG_L1C2("** Fragmentation failed [ret=%d] **",ret); + } + else + { + _LOG_L4C1("Delayed write placed on write queue"); + iDelayedWriteToModem = EFalse; + } + } + + CPortC32InterfaceBase* port = GetC32Port(); + if (port) + port->ModemAndCsyToClientFlowCtrl(aFlowControl); + else + { + _LOG_L2C1("** GetC32Port() returned NULL **"); + } + + _LOG_L4C1("<>CChannelMgrBase::ReceivedV24Signals [aV24Signals=0x%x,iDlcNum=%d]", + aV24Signals,iDlcNum); + + CPortC32InterfaceBase* port = GetC32Port(); + if (port) + { + // Flow control + TFlowControl flowControl = EFlowControlOff; + + // FC (bit 2) + if (aV24Signals & 0x02) + { + _LOG_L4C2("FC=1 - modem dlc %d unable to accept frames",iDlcNum); + flowControl = EFlowControlOn; + _LOG_L4C1("flowControl On (i.e stop flow)"); + + // move frames for this dlc from write list to wait list + iPortFactory.GetCommWriterAo()->RemoveAnyDlcFramesOnWriteList(iDlcNum); + } + else + { + // move any frames for this dlc from wait to write list + iPortFactory.GetCommWriterAo()->RemoveAnyDlcFramesFromWaitList(iDlcNum); + } + + ModemAndCsyToClientFlowCtrl(flowControl); + + port->ReceivedV24Signals(aV24Signals); + } + else + { + _LOG_L2C1("** GetC32Port() returned NULL **"); + } + + _LOG_L4C1("<>CChannelMgrBase::WaitForChannelReady"); + + if (iMux0710Protocol.MaxRetriesReached()) + { + _LOG_L4C1("Mux Max Retries reached - so skip Channel Ready"); + } + else + { + // kick off an active object and wait for channel ready call back + if (iChannelReady) + { + _LOG_L4C2("iChannelReady=%d",iChannelReady); + } + else if (!iChannelObserverAo->IsActive()) + { + // start the active object. CSY will wait here until channel is ready + // nest active scheduler is used here as we did not want to block whole thread (reading/writing) + + iChannelObserverAo->StartWait(); + + // start a nested scheduling; blocks until CActiveScheduler::Stop() + // is called in DoCancel() + + // MAF look at use CActiveSchedulerWait instead of this + + // One basic assumption here is that CSY will process port open request one by one + // (although there may be mutiple port open requests from clients, c32 will call PortFactory::NewPortL + // one by one.) This assumption should be valid as it is only one thread for c32 + // if this assumption does not hold, headache follows. + _LOG_L4C1("Start wait for channel ready"); + + CActiveScheduler::Start(); + _LOG_L4C1("End wait for channel ready"); + } + else + { + _LOG_L4C1("We are here only when others are already waiting"); + } + } + _LOG_L4C1("<>CChannelMgrBase::TimedOut"); + + iTxCount--; + if (iTxCount > 0) // retransmit + { + _LOG_L4C2("iTxCount=%d",iTxCount); + + TInt ret = KErrNone; + if (iMscReplyExpected) + { + iMscReplyExpected = EFalse; + ret = SendMscCommand(iV24Signals); + } + else + { + switch(iChannelState) + { + case ECsyChannelStateParameterNegotiating: + ret = iMux0710Protocol.Create0710ControlFrame( + CMux0710Protocol::EUIH, iDlcNum, CMux0710Protocol::EParamNeg); + break; + case ECsyChannelStateConnecting: + ret = iMux0710Protocol.Create0710ControlFrame( + CMux0710Protocol::ESABM, iDlcNum); + break; + case ECsyChannelStateDisconnecting: + ret = iMux0710Protocol.Create0710ControlFrame( + CMux0710Protocol::EDISC, iDlcNum); + break; + default: + // should never reach here + _LOG_L1C1("** unexpected receiving timeout **"); + } + } + if (ret) + { + // Error sending - we shall just wait until the timeout and try again + _LOG_L1C2("** Error sending on dlc 0 [ret=%d] **",ret); + } + iTimeouter->Stop(); + iTimeouter->Start(iTimeoutVal); + } + else + { + _LOG_L1C1("** Retries expired **"); + if (iMscReplyExpected) + { + _LOG_L1C1("** Retries expired for MSC command **"); + iMscReplyExpected = EFalse; + } + + // we have problem communication, may need to reset? + iChannelState = ECsyChannelStateTransmitError; + NotifyChannelReady(); + } + + _LOG_L4C1("<IsActive()) + { + iChannelObserverAo->ChannelReady(); + } + } + +TInt CChannelMgrBase::SetCsyToModemFlowControl(TFlowControl aFlowControl) +/** + * + */ + { + _LOG_L4C3(">>CChannelMgrBase::SetCsyToModemFlowControl [aFlowControl=%d,iDlcNum=%d]", + aFlowControl,iDlcNum); + + TInt ret = KErrNone; + if (aFlowControl != iModemAllowedToSendFrames) + { + TUint8 v24Signals = iV24Signals; + TBool sendCommand = EFalse; + if (aFlowControl == EFlowControlOn) + { + _LOG_L4C1("aFlowControl = ON"); + if (v24Signals & 0x02) + { + _LOG_L4C1("** Flow control already set **"); + } + else + { + v24Signals |= 0x02; + sendCommand = ETrue; + } + } + else + { + _LOG_L4C1("aFlowControl = OFF"); + if (v24Signals & 0x02) + { + v24Signals ^= 0x02; + sendCommand = ETrue; + } + else + { + _LOG_L4C1("Flow control already off"); + } + } + if (sendCommand) + { + ret = SendMscCommand(v24Signals); + if (ret) + { + _LOG_L4C1("SendMscCommand failed"); + } + else + { + _LOG_L4C3("Csy to modem flow control changed %d -> %d", + iModemAllowedToSendFrames,aFlowControl); + iModemAllowedToSendFrames = aFlowControl; + } + } + } + + _LOG_L4C2("<