diff -r 000000000000 -r af10295192d8 linklayerprotocols/slipnif/SRC/SLIP.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linklayerprotocols/slipnif/SRC/SLIP.CPP Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,558 @@ +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +/** + @file SLIP.CPP +*/ + +#include +#include +#include +#include "SLIP.H" +#include "SLIP_VER.H" + +const TUint KSlashChar='\\'; //< back slash character + +// +// SLIP ESock bits +// + +CSlip::CSlip(CNifIfFactory& aFactory) + : CNifIfLink(aFactory) +/** +Constructor +*/ + { + __DECLARE_NAME(_S("CSlip")); + } + +CSlip::~CSlip() +/** +Destructor +*/ + { + } + +void CSlip::Info(TNifIfInfo& aInfo) const + { + + FillInInfo(aInfo); + } + +void CSlip::FillInInfo(TNifIfInfo& aInfo) + { + aInfo.iVersion = TVersion(KSlipMajorVersionNumber, KSlipMinorVersionNumber, KSlipBuildVersionNumber); + aInfo.iFlags = KNifIfIsBase | KNifIfUsesNotify | KNifIfIsLink | KNifIfCreatedByFactory; + _LIT(KSlip, "slip"); + aInfo.iName = KSlip; + aInfo.iProtocolSupported=KProtocolInetIp; + } + +void CSlip::BindL(TAny* aId) + { + if (iIpProtocol) + User::Leave(KErrAlreadyExists); + iIpProtocol = (CProtocolBase*)aId; + } + +TInt CSlip::Send(RMBufChain& aPacket, TAny*) + { + iSendPktQ.Append(aPacket); + iSendMBufs += aPacket.NumBufs()-1; + if (!(iFlags & KSlipSendInUse)) + DoSend(); + + return (iFlags & KSlipSendInUse) ? 0 : 1; + } + +TInt CSlip::State() + { + + return (iFlags & KSlipIsUp) ? ((iFlags & KSlipSendBusy) ? EIfBusy : EIfUp) : EIfDown; + } + +TInt CSlip::Control(TUint aLevel, TUint aName, TDes8& aOption, TAny* /*aSource*/) + { + if (aLevel!=KSOLInterface) + return KErrNotSupported; + + switch (aName) + { + case KSoIfInfo: + { + TSoIfInfo& opt = *(TSoIfInfo*)aOption.Ptr(); + TNifIfInfo info; + FillInInfo(info); + + opt.iName = info.iName; + TPortName port; + + TBuf columnName=TPtrC(MODEM); + columnName.Append(TChar(KSlashChar)); + columnName.Append(TPtrC(MODEM_CSY_NAME)); + iNotify->ReadDes(columnName, port); + port.LowerCase(); + _LIT(portNameFormat,"::%S"); + opt.iName.AppendFormat(portNameFormat, &port); + + opt.iFeatures = KIfIsPointToPoint | KIfIsDialup; + opt.iMtu = KSlipDefaultMtu; + opt.iSpeedMetric = (iFlags & KSlipIsUp) ? SpeedMetric() : 0; + return KErrNone; + } + + case KSoIfHardwareAddr: + return KErrNotSupported; + + case KSoIfConfig: + return KErrNotSupported; + } + + return KErrNotSupported; + } + +// +// SLIP NifMan bits +// + +CNifIfBase* CSlip::GetBinderL(const TDesC& aName) +/** +Interface Manager call to create a new Binder protocol +which SLIP ignores + +@param aName new binder protocol +*/ + { + + _LIT(KDescIp, "ip"); + _LIT(KDescIcmp, "icmp"); + if(aName.CompareF(KDescIp) && aName.CompareF(KDescIcmp)) + User::Leave(KErrNotSupported); + + return 0; + } + +TInt CSlip::Start() +/** +Interface Manager call to start and claim the io port +*/ + { + TInt res=PacketModeOn(); + if(res!=KErrNone) + return res; + iFlags |= KSlipIsUp; + iRecvBuf.SetMax(); + CommRead(iRecvBuf); + iIpProtocol->StartSending((CProtocolBase*)this); + iNotify->LinkLayerUp(); + iNotify->IfProgress(EIfProgressLinkUp, KErrNone); + return KErrNone; + } + +void CSlip::Stop(TInt aReason, MNifIfNotify::TAction aAction) +/** +Interface Manager call to stop and release the io port +*/ + { + iFlags &= ~KSlipIsUp; + PacketModeOff(); + iSendPktQ.Free(); + iSendPkt.Free(); + iSendMBuf->Free(); + iSendMBuf = NULL; + iRecvQ.Free(); + iRecvMBuf->Free(); + iRecvMBuf = NULL; + iRecvLen = 0; + iFlags &= KSlipRecvEscPend; + iNotify->LinkLayerDown(aReason, aAction); + iNotify->IfProgress(EIfProgressLinkDown, aReason); + } + +// +// SLIP Internal +// + +void CSlip::DoSend() + { + TBool flowon = EFalse; + + TUint8* bptr = (TUint8*)iSendBuf.Ptr(); + TUint8* bend = (bptr+iSendBuf.MaxLength())-1; // -1 allows no check in switch below + + TUint8* mptr = NULL; // CSW: set to NULL for ASSERT below + TUint8* mend = NULL; // CSW: set to NULL for ASSERT below + + if (iSendMBuf!=NULL) + { + mptr = iSendMPtr; + mend = iSendMBuf->EndPtr(); + } + + while (bptrPtr(); + mend = iSendMBuf->EndPtr(); + if (mptr==mend) + { + iSendMBuf->Free(); + iSendMBuf = NULL; + continue; // with next MBuf + } + } + } + __ASSERT_DEBUG( mptr, SlipPanic( PanicSlipAssert1 ) ); + switch (*mptr) + { + case KSlipEndCh: + *bptr++ = KSlipEscCh; + *bptr++ = KSlipEscEndCh; + break; + case KSlipEscCh: + *bptr++ = KSlipEscCh; + *bptr++ = KSlipEscEscCh; + break; + default: + *bptr++ = *mptr; + break; + } + + if (++mptr==mend) + { + iSendMBuf->Free(); + iSendMBuf = NULL; + } + } + +SendIt: + iSendMPtr = mptr; + TInt n = bend-bptr; + if (n>0) + { + iSendBuf.SetLength(bend-bptr); + CommWrite(iSendBuf); + iFlags |= KSlipSendInUse; + } + + if (flowon) + iIpProtocol->StartSending((CProtocolBase*)this); + } + +void CSlip::CommWriteComplete(TInt aStatus) + { + iFlags &= ~KSlipSendInUse; + switch (aStatus) + { + case KErrCommsLineFail: + LinkDown(aStatus); + break; + default: + if (iFlags & KSlipIsUp) + DoSend(); + } + } + +void CSlip::CommReadComplete(TInt aStatus) + { + switch (aStatus) + { + case KErrCommsFrame: + case KErrCommsOverrun: + case KErrCommsParity: + iRecvQ.Free(); + iRecvLen = 0; + iRecvMBuf->Free(); + iRecvMBuf = NULL; + iFlags &= KSlipRecvEscPend; + break; + case KErrNone: + DoRecv(); + break; + case KErrCommsLineFail: + default: + LinkDown(aStatus); + break; + } + if (iFlags & KSlipIsUp) + { + iRecvBuf.SetMax(); + CommRead(iRecvBuf); + } + } + + +void CSlip::DoRecv() + { + TUint8* bptr = (TUint8*)iRecvBuf.Ptr(); + TUint8* bend = bptr+iRecvBuf.Length(); + if (bend==bptr) + return; + + TUint8* mptr = NULL; // CSW: set to NULL for ASSERT below + TUint8* mend = NULL; // CSW: set to NULL for ASSERT below + TUint8 c; + + TInt ret; + + if (iRecvMBuf!=NULL) + { + mptr = iRecvMBuf->Ptr(); + mend = iRecvMBuf->EndPtr(); + } + + while (bptr0) + { + __ASSERT_DEBUG( mptr, SlipPanic( PanicSlipAssert3 ) ); + __ASSERT_DEBUG( mend, SlipPanic( PanicSlipAssert4 ) ); + iRecvMBuf->SetLength(mend-mptr); + RMBufPacket pkt; + TRAPD(mem, pkt.CreateL(iRecvQ, iRecvLen)); + if(mem!=KErrNone) + { + //We are out of memory + return; + } + pkt.Pack(); + iIpProtocol->Process(pkt, (CProtocolBase*)this); + iRecvMBuf = NULL; // Force a new allocation + iRecvLen = 0; + } + break; + case KSlipEscCh: + // State is ESC_RECVD + if (bptr==bend) + { + iFlags |= KSlipRecvEscPend; + __ASSERT_DEBUG( mptr, SlipPanic( PanicSlipAssert5 ) ); + iRecvMPtr = mptr; + return; + } + c = *bptr++; + if (c==KSlipEscEndCh) + c = KSlipEndCh; + else if (c==KSlipEscEscCh) + c = KSlipEscCh; + // Fall through... + default: + // Allocation defered to here to ensure that + // no data is lost due to pre-allocs failing. + if (iRecvMBuf==NULL) + { + TRAP(ret, iRecvMBuf = RMBuf::AllocL()); + if (ret!=KErrNone) + { + // Junk the packet so far + iRecvQ.Free(); + iRecvLen = 0; + iFlags &= ~KSlipRecvEscPend; + return; + } + else + { + mptr = iRecvMBuf->Ptr(); + mend = iRecvMBuf->EndPtr(); + } + } + __ASSERT_DEBUG( mptr, SlipPanic( PanicSlipAssert6 ) ); + __ASSERT_DEBUG( mend, SlipPanic( PanicSlipAssert7 ) ); + *mptr++ = c; + iRecvLen++; + if (mptr==mend) + { + iRecvQ.Append(iRecvMBuf); + iRecvMBuf = NULL; // Force a new allocation + } + break; + } + } + iFlags &= KSlipRecvEscPend; + __ASSERT_DEBUG( mptr, SlipPanic( PanicSlipAssert8 ) ); + iRecvMPtr = mptr; + } + + +void CSlip::LinkDown(TInt aReason) + { + + if(aReason!=KErrCommsLineFail) + { + iNotify->LinkLayerDown(aReason, MNifIfNotify::EDisconnect); + iNotify->IfProgress(EIfProgressLinkDown, aReason); + } + else + iNotify->LinkLayerDown(aReason, MNifIfNotify::EReconnect); + } + +TInt CSlip::SpeedMetric() + { + switch (iOrigConfig().iRate) + { + case EBps50: + return 50; + case EBps75: + return 75; + case EBps110: + return 110; + case EBps134: + return 134; + case EBps150: + return 150; + case EBps300: + return 300; + case EBps600: + return 600; + case EBps1200: + return 1200; + case EBps1800: + return 1800; + case EBps2000: + return 2000; + case EBps2400: + return 2400; + case EBps3600: + return 3600; + case EBps4800: + return 4800; + case EBps7200: + return 7200; + case EBps9600: + return 9600; + case EBps19200: + return 19200; + case EBps38400: + return 38400; + case EBps57600: + return 57600; + case EBps115200: + return 115200; +// case EBps230400: +// return 230400; +// case EBps460800: +// return 230400; +// case EBps921600: +// return 921600; + case EBpsSpecial: + return iOrigConfig().iSpecialRate; + default: + ; + } + return 0; + } + +TInt CSlip::PacketModeOn() +/** +Configure the comm port for our needs +*/ + { + TInt err; + if (iFlags & KSlipCommConfigOk) + return KErrNone; + + TName port; + TBuf columnName=TPtrC(MODEM); + columnName.Append(TChar(KSlashChar)); + columnName.Append(TPtrC(MODEM_PORT_NAME)); + iNotify->ReadDes(columnName, port); + + if (err = CommOpen(port, ECommShared), err!=KErrNone) + return err; + + iCommPort.Config(iOrigConfig); + TCommConfig cbuf = iOrigConfig; + TCommConfigV01 &cfg=cbuf(); + cfg.iTerminatorCount = 1; + cfg.iTerminator[0] = KSlipEndCh; + cfg.iHandshake |= (0 + // | KConfigObeyCTS + // | KConfigFailCTS + | KConfigObeyDSR + | KConfigFailDSR + | KConfigObeyDCD + | KConfigFailDCD + // | KConfigFreeRTS + // | KConfigFreeDTR + ); + if (err = iCommPort.SetConfig(cbuf), err!=KErrNone) + { + CommClose(); + return err; + } + + iFlags |= KSlipCommConfigOk; + return KErrNone; + } + +TInt CSlip::PacketModeOff() + { + TInt err = KErrNone; + + if (iFlags & KSlipCommConfigOk) + { + CommCancel(); + iFlags &= ~KSlipCommConfigOk; + err = iCommPort.SetConfig(iOrigConfig); + CommClose(); + } + return err; + } + +TInt CSlip::Notification(TAgentToNifEventType /*aEvent*/, void * /*aInfo*/) + { + // no timers in SLIP, so nothing to do! + return KErrNone; + } + +void CSlip::Restart(CNifIfBase*) +/** +SLIP doesn't support different network-layer binders, so we can't restart one! +*/ + {}