--- /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 <nifmbuf.h>
+#include <in_iface.h>
+#include <cdblen.h>
+#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<KCommsDbSvrMaxColumnNameLength> 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 (bptr<bend)
+ {
+ if (iSendMBuf==NULL)
+ {
+ if (iSendMBuf = iSendPkt.Remove(), iSendMBuf==NULL)
+ {
+ // End of frame
+ *bptr++ = KSlipEndCh;
+ RMBufPacket pkt;
+ if (!iSendPktQ.Remove(pkt))
+ goto SendIt;
+ pkt.Unpack();
+ pkt.FreeInfo();
+ iSendPkt.Assign(pkt);
+ iSendMBuf = iSendPkt.Remove();
+ }
+ else
+ {
+ if ((iFlags & KSlipSendBusy) && iSendMBufs<=iSendLoWat)
+ {
+ // Deferred Flow Enable
+ flowon = ETrue;
+ iFlags &= ~KSlipSendBusy;
+ }
+
+ mptr = iSendMBuf->Ptr();
+ 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 (bptr<bend)
+ {
+ if (!(iFlags & KSlipRecvEscPend))
+ c = *bptr++;
+ else
+ {
+ c = KSlipEscCh;
+ iFlags &= ~KSlipRecvEscPend;
+ }
+
+ switch (c)
+ {
+ case KSlipEndCh:
+ // State is END_RECVD
+ if (iRecvLen>0)
+ {
+ __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<KCommsDbSvrMaxColumnNameLength> 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!
+*/
+ {}