|
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 /** |
|
17 @file SLIP.CPP |
|
18 */ |
|
19 |
|
20 #include <nifmbuf.h> |
|
21 #include <in_iface.h> |
|
22 #include <cdblen.h> |
|
23 #include "SLIP.H" |
|
24 #include "SLIP_VER.H" |
|
25 |
|
26 const TUint KSlashChar='\\'; //< back slash character |
|
27 |
|
28 // |
|
29 // SLIP ESock bits |
|
30 // |
|
31 |
|
32 CSlip::CSlip(CNifIfFactory& aFactory) |
|
33 : CNifIfLink(aFactory) |
|
34 /** |
|
35 Constructor |
|
36 */ |
|
37 { |
|
38 __DECLARE_NAME(_S("CSlip")); |
|
39 } |
|
40 |
|
41 CSlip::~CSlip() |
|
42 /** |
|
43 Destructor |
|
44 */ |
|
45 { |
|
46 } |
|
47 |
|
48 void CSlip::Info(TNifIfInfo& aInfo) const |
|
49 { |
|
50 |
|
51 FillInInfo(aInfo); |
|
52 } |
|
53 |
|
54 void CSlip::FillInInfo(TNifIfInfo& aInfo) |
|
55 { |
|
56 aInfo.iVersion = TVersion(KSlipMajorVersionNumber, KSlipMinorVersionNumber, KSlipBuildVersionNumber); |
|
57 aInfo.iFlags = KNifIfIsBase | KNifIfUsesNotify | KNifIfIsLink | KNifIfCreatedByFactory; |
|
58 _LIT(KSlip, "slip"); |
|
59 aInfo.iName = KSlip; |
|
60 aInfo.iProtocolSupported=KProtocolInetIp; |
|
61 } |
|
62 |
|
63 void CSlip::BindL(TAny* aId) |
|
64 { |
|
65 if (iIpProtocol) |
|
66 User::Leave(KErrAlreadyExists); |
|
67 iIpProtocol = (CProtocolBase*)aId; |
|
68 } |
|
69 |
|
70 TInt CSlip::Send(RMBufChain& aPacket, TAny*) |
|
71 { |
|
72 iSendPktQ.Append(aPacket); |
|
73 iSendMBufs += aPacket.NumBufs()-1; |
|
74 if (!(iFlags & KSlipSendInUse)) |
|
75 DoSend(); |
|
76 |
|
77 return (iFlags & KSlipSendInUse) ? 0 : 1; |
|
78 } |
|
79 |
|
80 TInt CSlip::State() |
|
81 { |
|
82 |
|
83 return (iFlags & KSlipIsUp) ? ((iFlags & KSlipSendBusy) ? EIfBusy : EIfUp) : EIfDown; |
|
84 } |
|
85 |
|
86 TInt CSlip::Control(TUint aLevel, TUint aName, TDes8& aOption, TAny* /*aSource*/) |
|
87 { |
|
88 if (aLevel!=KSOLInterface) |
|
89 return KErrNotSupported; |
|
90 |
|
91 switch (aName) |
|
92 { |
|
93 case KSoIfInfo: |
|
94 { |
|
95 TSoIfInfo& opt = *(TSoIfInfo*)aOption.Ptr(); |
|
96 TNifIfInfo info; |
|
97 FillInInfo(info); |
|
98 |
|
99 opt.iName = info.iName; |
|
100 TPortName port; |
|
101 |
|
102 TBuf<KCommsDbSvrMaxColumnNameLength> columnName=TPtrC(MODEM); |
|
103 columnName.Append(TChar(KSlashChar)); |
|
104 columnName.Append(TPtrC(MODEM_CSY_NAME)); |
|
105 iNotify->ReadDes(columnName, port); |
|
106 port.LowerCase(); |
|
107 _LIT(portNameFormat,"::%S"); |
|
108 opt.iName.AppendFormat(portNameFormat, &port); |
|
109 |
|
110 opt.iFeatures = KIfIsPointToPoint | KIfIsDialup; |
|
111 opt.iMtu = KSlipDefaultMtu; |
|
112 opt.iSpeedMetric = (iFlags & KSlipIsUp) ? SpeedMetric() : 0; |
|
113 return KErrNone; |
|
114 } |
|
115 |
|
116 case KSoIfHardwareAddr: |
|
117 return KErrNotSupported; |
|
118 |
|
119 case KSoIfConfig: |
|
120 return KErrNotSupported; |
|
121 } |
|
122 |
|
123 return KErrNotSupported; |
|
124 } |
|
125 |
|
126 // |
|
127 // SLIP NifMan bits |
|
128 // |
|
129 |
|
130 CNifIfBase* CSlip::GetBinderL(const TDesC& aName) |
|
131 /** |
|
132 Interface Manager call to create a new Binder protocol |
|
133 which SLIP ignores |
|
134 |
|
135 @param aName new binder protocol |
|
136 */ |
|
137 { |
|
138 |
|
139 _LIT(KDescIp, "ip"); |
|
140 _LIT(KDescIcmp, "icmp"); |
|
141 if(aName.CompareF(KDescIp) && aName.CompareF(KDescIcmp)) |
|
142 User::Leave(KErrNotSupported); |
|
143 |
|
144 return 0; |
|
145 } |
|
146 |
|
147 TInt CSlip::Start() |
|
148 /** |
|
149 Interface Manager call to start and claim the io port |
|
150 */ |
|
151 { |
|
152 TInt res=PacketModeOn(); |
|
153 if(res!=KErrNone) |
|
154 return res; |
|
155 iFlags |= KSlipIsUp; |
|
156 iRecvBuf.SetMax(); |
|
157 CommRead(iRecvBuf); |
|
158 iIpProtocol->StartSending((CProtocolBase*)this); |
|
159 iNotify->LinkLayerUp(); |
|
160 iNotify->IfProgress(EIfProgressLinkUp, KErrNone); |
|
161 return KErrNone; |
|
162 } |
|
163 |
|
164 void CSlip::Stop(TInt aReason, MNifIfNotify::TAction aAction) |
|
165 /** |
|
166 Interface Manager call to stop and release the io port |
|
167 */ |
|
168 { |
|
169 iFlags &= ~KSlipIsUp; |
|
170 PacketModeOff(); |
|
171 iSendPktQ.Free(); |
|
172 iSendPkt.Free(); |
|
173 iSendMBuf->Free(); |
|
174 iSendMBuf = NULL; |
|
175 iRecvQ.Free(); |
|
176 iRecvMBuf->Free(); |
|
177 iRecvMBuf = NULL; |
|
178 iRecvLen = 0; |
|
179 iFlags &= KSlipRecvEscPend; |
|
180 iNotify->LinkLayerDown(aReason, aAction); |
|
181 iNotify->IfProgress(EIfProgressLinkDown, aReason); |
|
182 } |
|
183 |
|
184 // |
|
185 // SLIP Internal |
|
186 // |
|
187 |
|
188 void CSlip::DoSend() |
|
189 { |
|
190 TBool flowon = EFalse; |
|
191 |
|
192 TUint8* bptr = (TUint8*)iSendBuf.Ptr(); |
|
193 TUint8* bend = (bptr+iSendBuf.MaxLength())-1; // -1 allows no check in switch below |
|
194 |
|
195 TUint8* mptr = NULL; // CSW: set to NULL for ASSERT below |
|
196 TUint8* mend = NULL; // CSW: set to NULL for ASSERT below |
|
197 |
|
198 if (iSendMBuf!=NULL) |
|
199 { |
|
200 mptr = iSendMPtr; |
|
201 mend = iSendMBuf->EndPtr(); |
|
202 } |
|
203 |
|
204 while (bptr<bend) |
|
205 { |
|
206 if (iSendMBuf==NULL) |
|
207 { |
|
208 if (iSendMBuf = iSendPkt.Remove(), iSendMBuf==NULL) |
|
209 { |
|
210 // End of frame |
|
211 *bptr++ = KSlipEndCh; |
|
212 RMBufPacket pkt; |
|
213 if (!iSendPktQ.Remove(pkt)) |
|
214 goto SendIt; |
|
215 pkt.Unpack(); |
|
216 pkt.FreeInfo(); |
|
217 iSendPkt.Assign(pkt); |
|
218 iSendMBuf = iSendPkt.Remove(); |
|
219 } |
|
220 else |
|
221 { |
|
222 if ((iFlags & KSlipSendBusy) && iSendMBufs<=iSendLoWat) |
|
223 { |
|
224 // Deferred Flow Enable |
|
225 flowon = ETrue; |
|
226 iFlags &= ~KSlipSendBusy; |
|
227 } |
|
228 |
|
229 mptr = iSendMBuf->Ptr(); |
|
230 mend = iSendMBuf->EndPtr(); |
|
231 if (mptr==mend) |
|
232 { |
|
233 iSendMBuf->Free(); |
|
234 iSendMBuf = NULL; |
|
235 continue; // with next MBuf |
|
236 } |
|
237 } |
|
238 } |
|
239 __ASSERT_DEBUG( mptr, SlipPanic( PanicSlipAssert1 ) ); |
|
240 switch (*mptr) |
|
241 { |
|
242 case KSlipEndCh: |
|
243 *bptr++ = KSlipEscCh; |
|
244 *bptr++ = KSlipEscEndCh; |
|
245 break; |
|
246 case KSlipEscCh: |
|
247 *bptr++ = KSlipEscCh; |
|
248 *bptr++ = KSlipEscEscCh; |
|
249 break; |
|
250 default: |
|
251 *bptr++ = *mptr; |
|
252 break; |
|
253 } |
|
254 |
|
255 if (++mptr==mend) |
|
256 { |
|
257 iSendMBuf->Free(); |
|
258 iSendMBuf = NULL; |
|
259 } |
|
260 } |
|
261 |
|
262 SendIt: |
|
263 iSendMPtr = mptr; |
|
264 TInt n = bend-bptr; |
|
265 if (n>0) |
|
266 { |
|
267 iSendBuf.SetLength(bend-bptr); |
|
268 CommWrite(iSendBuf); |
|
269 iFlags |= KSlipSendInUse; |
|
270 } |
|
271 |
|
272 if (flowon) |
|
273 iIpProtocol->StartSending((CProtocolBase*)this); |
|
274 } |
|
275 |
|
276 void CSlip::CommWriteComplete(TInt aStatus) |
|
277 { |
|
278 iFlags &= ~KSlipSendInUse; |
|
279 switch (aStatus) |
|
280 { |
|
281 case KErrCommsLineFail: |
|
282 LinkDown(aStatus); |
|
283 break; |
|
284 default: |
|
285 if (iFlags & KSlipIsUp) |
|
286 DoSend(); |
|
287 } |
|
288 } |
|
289 |
|
290 void CSlip::CommReadComplete(TInt aStatus) |
|
291 { |
|
292 switch (aStatus) |
|
293 { |
|
294 case KErrCommsFrame: |
|
295 case KErrCommsOverrun: |
|
296 case KErrCommsParity: |
|
297 iRecvQ.Free(); |
|
298 iRecvLen = 0; |
|
299 iRecvMBuf->Free(); |
|
300 iRecvMBuf = NULL; |
|
301 iFlags &= KSlipRecvEscPend; |
|
302 break; |
|
303 case KErrNone: |
|
304 DoRecv(); |
|
305 break; |
|
306 case KErrCommsLineFail: |
|
307 default: |
|
308 LinkDown(aStatus); |
|
309 break; |
|
310 } |
|
311 if (iFlags & KSlipIsUp) |
|
312 { |
|
313 iRecvBuf.SetMax(); |
|
314 CommRead(iRecvBuf); |
|
315 } |
|
316 } |
|
317 |
|
318 |
|
319 void CSlip::DoRecv() |
|
320 { |
|
321 TUint8* bptr = (TUint8*)iRecvBuf.Ptr(); |
|
322 TUint8* bend = bptr+iRecvBuf.Length(); |
|
323 if (bend==bptr) |
|
324 return; |
|
325 |
|
326 TUint8* mptr = NULL; // CSW: set to NULL for ASSERT below |
|
327 TUint8* mend = NULL; // CSW: set to NULL for ASSERT below |
|
328 TUint8 c; |
|
329 |
|
330 TInt ret; |
|
331 |
|
332 if (iRecvMBuf!=NULL) |
|
333 { |
|
334 mptr = iRecvMBuf->Ptr(); |
|
335 mend = iRecvMBuf->EndPtr(); |
|
336 } |
|
337 |
|
338 while (bptr<bend) |
|
339 { |
|
340 if (!(iFlags & KSlipRecvEscPend)) |
|
341 c = *bptr++; |
|
342 else |
|
343 { |
|
344 c = KSlipEscCh; |
|
345 iFlags &= ~KSlipRecvEscPend; |
|
346 } |
|
347 |
|
348 switch (c) |
|
349 { |
|
350 case KSlipEndCh: |
|
351 // State is END_RECVD |
|
352 if (iRecvLen>0) |
|
353 { |
|
354 __ASSERT_DEBUG( mptr, SlipPanic( PanicSlipAssert3 ) ); |
|
355 __ASSERT_DEBUG( mend, SlipPanic( PanicSlipAssert4 ) ); |
|
356 iRecvMBuf->SetLength(mend-mptr); |
|
357 RMBufPacket pkt; |
|
358 TRAPD(mem, pkt.CreateL(iRecvQ, iRecvLen)); |
|
359 if(mem!=KErrNone) |
|
360 { |
|
361 //We are out of memory |
|
362 return; |
|
363 } |
|
364 pkt.Pack(); |
|
365 iIpProtocol->Process(pkt, (CProtocolBase*)this); |
|
366 iRecvMBuf = NULL; // Force a new allocation |
|
367 iRecvLen = 0; |
|
368 } |
|
369 break; |
|
370 case KSlipEscCh: |
|
371 // State is ESC_RECVD |
|
372 if (bptr==bend) |
|
373 { |
|
374 iFlags |= KSlipRecvEscPend; |
|
375 __ASSERT_DEBUG( mptr, SlipPanic( PanicSlipAssert5 ) ); |
|
376 iRecvMPtr = mptr; |
|
377 return; |
|
378 } |
|
379 c = *bptr++; |
|
380 if (c==KSlipEscEndCh) |
|
381 c = KSlipEndCh; |
|
382 else if (c==KSlipEscEscCh) |
|
383 c = KSlipEscCh; |
|
384 // Fall through... |
|
385 default: |
|
386 // Allocation defered to here to ensure that |
|
387 // no data is lost due to pre-allocs failing. |
|
388 if (iRecvMBuf==NULL) |
|
389 { |
|
390 TRAP(ret, iRecvMBuf = RMBuf::AllocL()); |
|
391 if (ret!=KErrNone) |
|
392 { |
|
393 // Junk the packet so far |
|
394 iRecvQ.Free(); |
|
395 iRecvLen = 0; |
|
396 iFlags &= ~KSlipRecvEscPend; |
|
397 return; |
|
398 } |
|
399 else |
|
400 { |
|
401 mptr = iRecvMBuf->Ptr(); |
|
402 mend = iRecvMBuf->EndPtr(); |
|
403 } |
|
404 } |
|
405 __ASSERT_DEBUG( mptr, SlipPanic( PanicSlipAssert6 ) ); |
|
406 __ASSERT_DEBUG( mend, SlipPanic( PanicSlipAssert7 ) ); |
|
407 *mptr++ = c; |
|
408 iRecvLen++; |
|
409 if (mptr==mend) |
|
410 { |
|
411 iRecvQ.Append(iRecvMBuf); |
|
412 iRecvMBuf = NULL; // Force a new allocation |
|
413 } |
|
414 break; |
|
415 } |
|
416 } |
|
417 iFlags &= KSlipRecvEscPend; |
|
418 __ASSERT_DEBUG( mptr, SlipPanic( PanicSlipAssert8 ) ); |
|
419 iRecvMPtr = mptr; |
|
420 } |
|
421 |
|
422 |
|
423 void CSlip::LinkDown(TInt aReason) |
|
424 { |
|
425 |
|
426 if(aReason!=KErrCommsLineFail) |
|
427 { |
|
428 iNotify->LinkLayerDown(aReason, MNifIfNotify::EDisconnect); |
|
429 iNotify->IfProgress(EIfProgressLinkDown, aReason); |
|
430 } |
|
431 else |
|
432 iNotify->LinkLayerDown(aReason, MNifIfNotify::EReconnect); |
|
433 } |
|
434 |
|
435 TInt CSlip::SpeedMetric() |
|
436 { |
|
437 switch (iOrigConfig().iRate) |
|
438 { |
|
439 case EBps50: |
|
440 return 50; |
|
441 case EBps75: |
|
442 return 75; |
|
443 case EBps110: |
|
444 return 110; |
|
445 case EBps134: |
|
446 return 134; |
|
447 case EBps150: |
|
448 return 150; |
|
449 case EBps300: |
|
450 return 300; |
|
451 case EBps600: |
|
452 return 600; |
|
453 case EBps1200: |
|
454 return 1200; |
|
455 case EBps1800: |
|
456 return 1800; |
|
457 case EBps2000: |
|
458 return 2000; |
|
459 case EBps2400: |
|
460 return 2400; |
|
461 case EBps3600: |
|
462 return 3600; |
|
463 case EBps4800: |
|
464 return 4800; |
|
465 case EBps7200: |
|
466 return 7200; |
|
467 case EBps9600: |
|
468 return 9600; |
|
469 case EBps19200: |
|
470 return 19200; |
|
471 case EBps38400: |
|
472 return 38400; |
|
473 case EBps57600: |
|
474 return 57600; |
|
475 case EBps115200: |
|
476 return 115200; |
|
477 // case EBps230400: |
|
478 // return 230400; |
|
479 // case EBps460800: |
|
480 // return 230400; |
|
481 // case EBps921600: |
|
482 // return 921600; |
|
483 case EBpsSpecial: |
|
484 return iOrigConfig().iSpecialRate; |
|
485 default: |
|
486 ; |
|
487 } |
|
488 return 0; |
|
489 } |
|
490 |
|
491 TInt CSlip::PacketModeOn() |
|
492 /** |
|
493 Configure the comm port for our needs |
|
494 */ |
|
495 { |
|
496 TInt err; |
|
497 if (iFlags & KSlipCommConfigOk) |
|
498 return KErrNone; |
|
499 |
|
500 TName port; |
|
501 TBuf<KCommsDbSvrMaxColumnNameLength> columnName=TPtrC(MODEM); |
|
502 columnName.Append(TChar(KSlashChar)); |
|
503 columnName.Append(TPtrC(MODEM_PORT_NAME)); |
|
504 iNotify->ReadDes(columnName, port); |
|
505 |
|
506 if (err = CommOpen(port, ECommShared), err!=KErrNone) |
|
507 return err; |
|
508 |
|
509 iCommPort.Config(iOrigConfig); |
|
510 TCommConfig cbuf = iOrigConfig; |
|
511 TCommConfigV01 &cfg=cbuf(); |
|
512 cfg.iTerminatorCount = 1; |
|
513 cfg.iTerminator[0] = KSlipEndCh; |
|
514 cfg.iHandshake |= (0 |
|
515 // | KConfigObeyCTS |
|
516 // | KConfigFailCTS |
|
517 | KConfigObeyDSR |
|
518 | KConfigFailDSR |
|
519 | KConfigObeyDCD |
|
520 | KConfigFailDCD |
|
521 // | KConfigFreeRTS |
|
522 // | KConfigFreeDTR |
|
523 ); |
|
524 if (err = iCommPort.SetConfig(cbuf), err!=KErrNone) |
|
525 { |
|
526 CommClose(); |
|
527 return err; |
|
528 } |
|
529 |
|
530 iFlags |= KSlipCommConfigOk; |
|
531 return KErrNone; |
|
532 } |
|
533 |
|
534 TInt CSlip::PacketModeOff() |
|
535 { |
|
536 TInt err = KErrNone; |
|
537 |
|
538 if (iFlags & KSlipCommConfigOk) |
|
539 { |
|
540 CommCancel(); |
|
541 iFlags &= ~KSlipCommConfigOk; |
|
542 err = iCommPort.SetConfig(iOrigConfig); |
|
543 CommClose(); |
|
544 } |
|
545 return err; |
|
546 } |
|
547 |
|
548 TInt CSlip::Notification(TAgentToNifEventType /*aEvent*/, void * /*aInfo*/) |
|
549 { |
|
550 // no timers in SLIP, so nothing to do! |
|
551 return KErrNone; |
|
552 } |
|
553 |
|
554 void CSlip::Restart(CNifIfBase*) |
|
555 /** |
|
556 SLIP doesn't support different network-layer binders, so we can't restart one! |
|
557 */ |
|
558 {} |