|
1 // Copyright (c) 2006-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 |
|
18 @internalComponent |
|
19 */ |
|
20 |
|
21 #include "hctlbcspFrameQueue.h" |
|
22 |
|
23 #include "hctlbcsp.h" |
|
24 #include "hctlbcspconsts.h" |
|
25 #include "hctlbcspsequencer.h" |
|
26 #include "bcsputils.h" |
|
27 #include "debug.h" |
|
28 #include "hctlbcspframe.h" |
|
29 |
|
30 CHCTLBcspWindow::CHCTLBcspWindow(TInt aWindowSize, TInt aNumberOfSeqIds) |
|
31 : iEndOfWindow(aWindowSize - 1), |
|
32 iWindowSize(aWindowSize), |
|
33 iNumberOfSeqIds(aNumberOfSeqIds), |
|
34 iFrameQue(_FOFF(CTxHctlBcspFrame,iLink)) |
|
35 { |
|
36 LOG_FUNC |
|
37 } |
|
38 |
|
39 CHCTLBcspWindow* CHCTLBcspWindow::NewL(TInt aWindowSize, TInt aFrameSize, TInt aNumberOfSeqIds) |
|
40 { |
|
41 LOG_STATIC_FUNC |
|
42 |
|
43 CHCTLBcspWindow *self = new (ELeave) CHCTLBcspWindow(aWindowSize, aNumberOfSeqIds); |
|
44 CleanupStack::PushL(self); |
|
45 self->ConstructL(aFrameSize); |
|
46 CleanupStack::Pop(self); |
|
47 return self; |
|
48 } |
|
49 |
|
50 void CHCTLBcspWindow::ConstructL(TInt aFrameSize) |
|
51 { |
|
52 LOG_FUNC |
|
53 |
|
54 for(TInt i=0;i<iWindowSize;i++) |
|
55 { |
|
56 CTxHctlBcspFrame *frame = CTxHctlBcspFrame::NewL(aFrameSize); |
|
57 frame->Reset(); |
|
58 iFrameQue.AddLast(*frame); |
|
59 |
|
60 #ifdef _DEBUG_WINDOW |
|
61 LOG1(_L8("frame added 0x%08x"),frame); |
|
62 #endif |
|
63 } |
|
64 #ifdef _DEBUG_WINDOW |
|
65 TraceWindowVars(); |
|
66 TraceQueue(); |
|
67 #endif |
|
68 } |
|
69 |
|
70 CHCTLBcspWindow::~CHCTLBcspWindow() |
|
71 { |
|
72 LOG_FUNC |
|
73 |
|
74 for (TInt i=0;i<iWindowSize;i++) |
|
75 { |
|
76 CTxHctlBcspFrame* frame = iFrameQue.First(); |
|
77 iFrameQue.Remove(*frame); |
|
78 delete frame; |
|
79 } |
|
80 } |
|
81 |
|
82 TInt CHCTLBcspWindow::StartOfWindow() const |
|
83 { |
|
84 LOG_FUNC |
|
85 |
|
86 return iStartOfWindow; |
|
87 } |
|
88 |
|
89 TInt CHCTLBcspWindow::ToSeqId(TInt aIndex) const |
|
90 { |
|
91 LOG_FUNC |
|
92 |
|
93 return (aIndex + iStartOfWindow)%iNumberOfSeqIds; |
|
94 } |
|
95 |
|
96 TInt CHCTLBcspWindow::ToWindowIndex(TInt aSeqId) const |
|
97 { |
|
98 LOG_FUNC |
|
99 |
|
100 TInt index = aSeqId - iStartOfWindow; |
|
101 if ( index < 0 ) |
|
102 { |
|
103 index += iNumberOfSeqIds; |
|
104 } |
|
105 return index; |
|
106 } |
|
107 |
|
108 void CHCTLBcspWindow::IncrementSeqId(TInt &aSeqId) const |
|
109 { |
|
110 aSeqId++; |
|
111 aSeqId %= iNumberOfSeqIds; |
|
112 } |
|
113 |
|
114 |
|
115 CTxHctlBcspFrame* CHCTLBcspWindow::GetFrame(TInt aIndex) |
|
116 /** |
|
117 Method to retrieve a frame for transmission |
|
118 */ |
|
119 { |
|
120 LOG_FUNC |
|
121 |
|
122 __TEST_INVARIANT; |
|
123 |
|
124 TInt index = ToWindowIndex(aIndex); |
|
125 __ASSERT_DEBUG((index>=0) && (index<iWindowSize), PANIC(KBcspPanicCat, EBadBcspFrame)); |
|
126 |
|
127 TSglQueIter<CTxHctlBcspFrame> iter(iFrameQue); |
|
128 CTxHctlBcspFrame* frame = iter++; |
|
129 |
|
130 while ( index > 0 ) |
|
131 { |
|
132 frame = iter++; |
|
133 index--; |
|
134 } |
|
135 |
|
136 #ifdef _DEBUG_WINDOW |
|
137 LOG2(_L8("frame got 0x%08x (index:%d)"), frame, aIndex); |
|
138 #endif |
|
139 |
|
140 return frame; |
|
141 } |
|
142 |
|
143 TInt CHCTLBcspWindow::FreeFrames() |
|
144 /** |
|
145 Method to free up space in transmit queue for sending more BCSP frames |
|
146 */ |
|
147 { |
|
148 LOG_FUNC |
|
149 |
|
150 __TEST_INVARIANT; |
|
151 |
|
152 return ToWindowIndex(iEndOfWindow) - ToWindowIndex(iWritePosition); |
|
153 } |
|
154 |
|
155 CTxHctlBcspFrame *CHCTLBcspWindow::WriteFrame() |
|
156 /** |
|
157 Method to Write a frame to the frame queue |
|
158 */ |
|
159 { |
|
160 LOG_FUNC |
|
161 |
|
162 CTxHctlBcspFrame *frame = NULL; |
|
163 |
|
164 __TEST_INVARIANT; |
|
165 |
|
166 if ( iWritePosition != iEndOfWindow ) |
|
167 { |
|
168 frame = GetFrame(iWritePosition); |
|
169 |
|
170 if(frame) |
|
171 { |
|
172 IncrementSeqId(iWritePosition); |
|
173 // Make sure we're not returning a valid frame to be overwritten |
|
174 __ASSERT_DEBUG(!frame->IsValid(), PANIC(KBcspPanicCat, EBadBcspFrame)); |
|
175 } |
|
176 else |
|
177 { |
|
178 #ifdef _DEBUG_WINDOW |
|
179 FTRACE(FPrintBCSP(_L("Bcsp frame queue blocked (panic now deprecated)"))); |
|
180 #endif |
|
181 } |
|
182 |
|
183 #ifdef _DEBUG_WINDOW |
|
184 LOG(_L8("Post Write")); |
|
185 TraceWindowVars(); |
|
186 TraceQueue(); |
|
187 #endif |
|
188 } |
|
189 |
|
190 __TEST_INVARIANT; |
|
191 |
|
192 return frame; |
|
193 } |
|
194 |
|
195 CTxHctlBcspFrame *CHCTLBcspWindow::ReadFrame() |
|
196 /** |
|
197 Method to read a frame from the Transmit Queue |
|
198 |
|
199 @return CTxHctlBcspFrame * frame |
|
200 */ |
|
201 { |
|
202 LOG_FUNC |
|
203 |
|
204 CTxHctlBcspFrame *frame = NULL; |
|
205 |
|
206 __TEST_INVARIANT; |
|
207 |
|
208 if ( iReadPosition != iWritePosition ) |
|
209 { |
|
210 frame = GetFrame(iReadPosition); |
|
211 frame->SetSequence(static_cast<TUint8>(iReadPosition)); |
|
212 |
|
213 if (iReadPosition == iHighReadPosition) |
|
214 { |
|
215 IncrementSeqId(iHighReadPosition); |
|
216 } |
|
217 IncrementSeqId(iReadPosition); |
|
218 |
|
219 #ifdef _DEBUG_WINDOW |
|
220 LOG(_L8("Post Read")); |
|
221 TraceWindowVars(); |
|
222 TraceQueue(); |
|
223 #endif |
|
224 // Make sure we're returning a valid frame to be used |
|
225 __ASSERT_DEBUG(frame->IsValid(), PANIC(KBcspPanicCat, EBadBcspFrame)); |
|
226 } |
|
227 |
|
228 __TEST_INVARIANT; |
|
229 |
|
230 return frame; |
|
231 } |
|
232 |
|
233 TBool CHCTLBcspWindow::Acknowledged(TInt aAckNo) |
|
234 /** |
|
235 Method to handle TxFrame acknowledgement |
|
236 Remove the frame that is acknowledged |
|
237 @param current Rx Ack value, KErrTimedOut if ack timed out |
|
238 */ |
|
239 { |
|
240 LOG_FUNC |
|
241 |
|
242 TBool framesRemainingInWindow = EFalse; |
|
243 |
|
244 #ifdef _DEBUG_WINDOW |
|
245 LOG(_L8("Pre Ack")); |
|
246 TraceWindowVars(); |
|
247 #endif |
|
248 |
|
249 __TEST_INVARIANT; |
|
250 |
|
251 const TBool resetWindow = ((aAckNo >= 0) && (ToWindowIndex(aAckNo) > ToWindowIndex(iHighReadPosition))) ? ETrue : EFalse; |
|
252 |
|
253 if (resetWindow) |
|
254 { |
|
255 #ifdef _DEBUG_WINDOW |
|
256 LOG1(_L8("Ack for unsent packet (%d), resetting entire window!!!"), aAckNo); |
|
257 #endif |
|
258 // reset frames |
|
259 TSglQueIter<CTxHctlBcspFrame> iter(iFrameQue); |
|
260 CTxHctlBcspFrame *frame = iter++; |
|
261 |
|
262 while (iter) |
|
263 { |
|
264 frame->Reset(); |
|
265 frame = iter++; |
|
266 } |
|
267 |
|
268 //reset window variables |
|
269 iStartOfWindow = aAckNo; |
|
270 iStartOfWindow %= iNumberOfSeqIds; |
|
271 |
|
272 iEndOfWindow = iStartOfWindow + iWindowSize-1; |
|
273 iEndOfWindow %= iNumberOfSeqIds; |
|
274 |
|
275 iWritePosition = iHighReadPosition = iReadPosition = iStartOfWindow; |
|
276 |
|
277 framesRemainingInWindow = ETrue; |
|
278 } |
|
279 else if (iReadPosition != iStartOfWindow) // frames waiting to be acknowledged |
|
280 { |
|
281 LOG1(_L("Ack(%d)"), aAckNo); |
|
282 |
|
283 if ( aAckNo >= 0 ) |
|
284 { |
|
285 aAckNo %= iNumberOfSeqIds; // Make sure we wrap around at the end of the window |
|
286 LOG1(_L8("Ack(%d)"), aAckNo); |
|
287 |
|
288 // TInt readIndex = ackWindowIndex; |
|
289 TBool found = EFalse; |
|
290 TInt i = iStartOfWindow; |
|
291 |
|
292 while(!found && (i != iEndOfWindow)) |
|
293 { |
|
294 if((i == aAckNo)) |
|
295 { |
|
296 found = ETrue; |
|
297 } |
|
298 else if(!found) |
|
299 { |
|
300 // This frame is before the ackWindowIndex therefore we should reset it |
|
301 CTxHctlBcspFrame* frame = iFrameQue.First(); |
|
302 frame->Reset(); |
|
303 iFrameQue.Remove(*frame); |
|
304 iFrameQue.AddLast(*frame); |
|
305 } |
|
306 IncrementSeqId(i); |
|
307 } |
|
308 |
|
309 iStartOfWindow = aAckNo; |
|
310 iStartOfWindow %= iNumberOfSeqIds; |
|
311 |
|
312 iEndOfWindow = iStartOfWindow + iWindowSize - 1; |
|
313 iEndOfWindow %= iNumberOfSeqIds; |
|
314 } |
|
315 |
|
316 // We've just had an acknowledgement so we need to resend from the start of the buffer |
|
317 iReadPosition = iStartOfWindow; |
|
318 |
|
319 // We've just rationalised the window. The write position can remain where it was. |
|
320 framesRemainingInWindow = ETrue; |
|
321 } |
|
322 |
|
323 #ifdef _DEBUG_WINDOW |
|
324 LOG(_L("Post Ack")); |
|
325 TraceWindowVars(); |
|
326 TraceQueue(); |
|
327 #endif |
|
328 |
|
329 __TEST_INVARIANT; |
|
330 |
|
331 return framesRemainingInWindow; |
|
332 } |
|
333 |
|
334 void CHCTLBcspWindow::__DbgTestInvariant(void) const |
|
335 /** |
|
336 Debug method |
|
337 */ |
|
338 { |
|
339 // Check that the class is internally consistent |
|
340 __ASSERT_DEBUG(iNumberOfSeqIds>0, User::Invariant()); |
|
341 __ASSERT_DEBUG((iWindowSize>0) && (iWindowSize <= iNumberOfSeqIds), User::Invariant()); |
|
342 |
|
343 __ASSERT_DEBUG((iStartOfWindow>=0) && (iStartOfWindow<=iNumberOfSeqIds), User::Invariant()); |
|
344 __ASSERT_DEBUG((iEndOfWindow>=0) && (iEndOfWindow<=iNumberOfSeqIds), User::Invariant()); |
|
345 __ASSERT_DEBUG((iReadPosition>=0 ) && (iReadPosition<=iNumberOfSeqIds), User::Invariant()); |
|
346 __ASSERT_DEBUG((iHighReadPosition>=0 ) && (iHighReadPosition<=iNumberOfSeqIds),User::Invariant()); |
|
347 __ASSERT_DEBUG((iWritePosition>=0) && (iWritePosition<=iNumberOfSeqIds), User::Invariant()); |
|
348 |
|
349 TInt winSize = iEndOfWindow - iStartOfWindow + 1; |
|
350 if ( winSize < 0 ) |
|
351 { |
|
352 winSize += iNumberOfSeqIds; |
|
353 } |
|
354 __ASSERT_DEBUG(winSize == iWindowSize, User::Invariant()); |
|
355 if ( iWritePosition != iEndOfWindow ) |
|
356 { |
|
357 __ASSERT_DEBUG(ToWindowIndex(iReadPosition) <= ToWindowIndex(iHighReadPosition), User::Invariant()); |
|
358 __ASSERT_DEBUG(ToWindowIndex(iHighReadPosition) <= ToWindowIndex(iWritePosition), User::Invariant()); |
|
359 } |
|
360 } |
|
361 |
|
362 #ifdef _DEBUG_WINDOW |
|
363 void CHCTLBcspWindow::TraceWindowVars() const |
|
364 /** |
|
365 Debug method |
|
366 */ |
|
367 { |
|
368 LOG_FUNC |
|
369 RProcess process; |
|
370 RThread thread; |
|
371 TName pName = process.Name(); |
|
372 TName tName = thread.Name(); |
|
373 LOG1(_L8("Process : %S"), &pName); |
|
374 LOG1(_L8("Thread : %S"), &tName); |
|
375 LOG6(_L8("this : 0x%08x SOW : %d, RP : %d, HRP: %d, WP : %d, EOW :%d"),this, iStartOfWindow, iReadPosition, iHighReadPosition, iWritePosition, iEndOfWindow); |
|
376 } |
|
377 |
|
378 void CHCTLBcspWindow::TraceQueue() |
|
379 /** |
|
380 Debug method |
|
381 */ |
|
382 { |
|
383 LOG_FUNC |
|
384 LOG1(_L8("Queue Dumping this 0x%08x"), this); |
|
385 TSglQueIter<CTxHctlBcspFrame> iter(iFrameQue); |
|
386 CTxHctlBcspFrame *frame = iter++; |
|
387 |
|
388 _LIT(KSpace, " "); |
|
389 _LIT(KWriteMarker, "W"); |
|
390 _LIT(KHighMarker, "H"); |
|
391 _LIT(KReadMarker, "R"); |
|
392 |
|
393 TInt index = 0; |
|
394 while ( index < iWindowSize ) |
|
395 { |
|
396 LOG6(_L8("%S %S %S this: 0x%08x, frame : 0x%08x, %d"), |
|
397 (index == ToWindowIndex(iWritePosition)) ? &KWriteMarker : &KSpace, |
|
398 (index == ToWindowIndex(iHighReadPosition)) ? &KHighMarker : &KSpace, |
|
399 (index == ToWindowIndex(iReadPosition)) ? &KReadMarker : &KSpace, |
|
400 this, |
|
401 frame, |
|
402 frame->IsValid() |
|
403 ); |
|
404 frame = iter++; |
|
405 index++; |
|
406 } |
|
407 } |
|
408 #endif |
|
409 |
|
410 void CHCTLBcspWindow::Reset() |
|
411 { |
|
412 LOG_FUNC |
|
413 |
|
414 for(TInt i=0;i<iWindowSize;i++) |
|
415 { |
|
416 CTxHctlBcspFrame* frame = iFrameQue.First(); |
|
417 frame->Reset(); |
|
418 iFrameQue.Remove(*frame); |
|
419 iFrameQue.AddLast(*frame); |
|
420 |
|
421 #ifdef _DEBUG_WINDOW |
|
422 LOG1(_L8("frame reset 0x%08x"),frame); |
|
423 #endif |
|
424 } |
|
425 |
|
426 iStartOfWindow = 0; |
|
427 iReadPosition = 0; |
|
428 iHighReadPosition = 0; |
|
429 iWritePosition = 0; |
|
430 iEndOfWindow = iWindowSize - 1; |
|
431 |
|
432 #ifdef _DEBUG_WINDOW |
|
433 LOG(_L8("Reset")); |
|
434 |
|
435 TraceWindowVars(); |
|
436 TraceQueue(); |
|
437 #endif |
|
438 } |
|
439 |
|
440 /* ********************************************************************************************* |
|
441 * Frame Queue - Manages the frame queues for both Reliable and Unreliable data transfer |
|
442 * ********************************************************************************************* */ |
|
443 CHCTLBcspFrameQueue* CHCTLBcspFrameQueue::NewL(CHCTLBcsp &aBcsp) |
|
444 { |
|
445 LOG_STATIC_FUNC |
|
446 |
|
447 CHCTLBcspFrameQueue *self = new (ELeave) CHCTLBcspFrameQueue(aBcsp); |
|
448 CleanupStack::PushL(self); |
|
449 self->ConstructL(); |
|
450 CleanupStack::Pop(self); |
|
451 return self; |
|
452 } |
|
453 |
|
454 void CHCTLBcspFrameQueue::ConstructL() |
|
455 { |
|
456 LOG_FUNC |
|
457 |
|
458 // Create the queues |
|
459 iReliableQueue = CHCTLBcspWindow::NewL(KBcspReliableWindowSize, |
|
460 KMaxReliablePayloadSize, |
|
461 KMaxBcspWindowSize); |
|
462 |
|
463 iUnreliableQueue = CHCTLBcspWindow::NewL(KBcspUnreliableQueueSize, |
|
464 KMaxUnreliablePayloadSize, |
|
465 KBcspUnreliableQueueSize+1); |
|
466 |
|
467 // Room for Slip encoded packet is twice the size of a full BCSP Packet + 2 for the 0xC0 bytes |
|
468 iSlipEncodedFrame = HBufC8::NewL(2 + ((KMaxReliablePayloadSize + KBcspHeaderBytes + KBcspCrcBytes) * 2)); |
|
469 } |
|
470 |
|
471 CHCTLBcspFrameQueue::CHCTLBcspFrameQueue(CHCTLBcsp& aBcsp) |
|
472 : iBcsp(aBcsp) |
|
473 { |
|
474 LOG_FUNC |
|
475 } |
|
476 |
|
477 CHCTLBcspFrameQueue::~CHCTLBcspFrameQueue() |
|
478 |
|
479 { |
|
480 LOG_FUNC |
|
481 |
|
482 delete iUnreliableQueue; |
|
483 delete iReliableQueue; |
|
484 delete iSlipEncodedFrame; |
|
485 } |
|
486 |
|
487 |
|
488 void CHCTLBcspFrameQueue::SetSequencer(CHCTLBcspSequencer& aSequencer) |
|
489 /** |
|
490 Simple method to initialise iSequencer with @param &aSequencer |
|
491 */ |
|
492 { |
|
493 LOG_FUNC |
|
494 |
|
495 iSequencer = &aSequencer; |
|
496 } |
|
497 |
|
498 TInt CHCTLBcspFrameQueue::GetNextFrame(TDesC8* &aFrame, TBool& aIsReliable) |
|
499 /** |
|
500 Method to get the next frame from the frame queue and then to build and slip encode it |
|
501 |
|
502 @param &aFrame |
|
503 @param aIsReliable a reference to a TBool which will be set to ETrue if the |
|
504 Frame is from the reliable queue. |
|
505 @return err |
|
506 */ |
|
507 { |
|
508 LOG_FUNC |
|
509 |
|
510 TInt err = KErrNone; |
|
511 |
|
512 CTxHctlBcspFrame *frame = iUnreliableQueue->ReadFrame(); |
|
513 |
|
514 if ( frame ) |
|
515 { |
|
516 // Got unreliable frame |
|
517 iUnreliableQueue->Acknowledged(iUnreliableQueue->StartOfWindow()+1); // Remove the first frame from the window |
|
518 frame->SetSequence(0); |
|
519 aIsReliable = EFalse; |
|
520 } |
|
521 else |
|
522 { |
|
523 // Couldn't get an unreliable frame, so ... get a reliable frame |
|
524 frame = iReliableQueue->ReadFrame(); |
|
525 |
|
526 if ( !frame ) |
|
527 { |
|
528 // We can't get a reliable frame either |
|
529 err = KErrBcspNothingToSend; |
|
530 aIsReliable = EFalse; |
|
531 } |
|
532 else |
|
533 { |
|
534 // We've got a reliable frame - increment the retry count |
|
535 frame->IncrementRetries(); |
|
536 frame->SetFlags(iSequencer->TxAck(), ETrue, ETrue); |
|
537 if ( frame->Retries() >= KTxRetryLimit ) |
|
538 { |
|
539 err = KErrBcspMaxRetries; |
|
540 } |
|
541 |
|
542 aIsReliable = ETrue; |
|
543 } |
|
544 } |
|
545 |
|
546 if ( !err ) |
|
547 { |
|
548 // No errors so far, so SlipEncode the frame into iSlipEncodedFrame |
|
549 frame->BuildFrame(); |
|
550 frame->SlipEncodeFrame(iSlipEncodedFrame->Des()); |
|
551 aFrame = iSlipEncodedFrame; |
|
552 |
|
553 #ifdef _DEBUG_WINDOW |
|
554 LOG(_L8("Got Frame")); |
|
555 LOGHEXRAW(frame->Payload().Ptr(), frame->PayloadLength()); |
|
556 |
|
557 LOG(_L8("Slip Encoded Frame")); |
|
558 LOGHEXRAW(aFrame->Ptr(), aFrame->Length()); |
|
559 #endif |
|
560 } |
|
561 else |
|
562 { |
|
563 // Just in case our return code is ignored :-> |
|
564 aFrame = NULL; |
|
565 } |
|
566 |
|
567 return err; |
|
568 } |
|
569 |
|
570 TBool CHCTLBcspFrameQueue::AckReceived(TInt aAckValue) |
|
571 /** |
|
572 Handle AckReceived @param aAckValue |
|
573 |
|
574 call Acknowledged method on relaible queue |
|
575 call CanSend() |
|
576 |
|
577 @return ETrue if there are unacknowledged packets remaining |
|
578 in the tx window. |
|
579 */ |
|
580 { |
|
581 LOG_FUNC |
|
582 |
|
583 TBool ret=iReliableQueue->Acknowledged(aAckValue); |
|
584 CanSend(); |
|
585 return ret; |
|
586 } |
|
587 |
|
588 void CHCTLBcspFrameQueue::AckTimeout() |
|
589 /** |
|
590 Handle Rx Ack timeout |
|
591 |
|
592 Inform reliable queue to resend frame |
|
593 CanSend |
|
594 Call iSequencer->WakeUp() to trigger the sequencer to pull frames for resending from the |
|
595 reliable frame queue |
|
596 */ |
|
597 { |
|
598 LOG_FUNC |
|
599 |
|
600 iReliableQueue->Acknowledged(KErrTimedOut); |
|
601 CanSend(); |
|
602 iSequencer->WakeUp(); |
|
603 } |
|
604 |
|
605 TInt CHCTLBcspFrameQueue::AddReliableFrame(const TDesC8 &aData, TUint8 aProtocolId) |
|
606 /** |
|
607 Method to add a frame to the Tx Reliable queue |
|
608 @param aData - HCI payload |
|
609 @param aProtocolId - ProtocolId eg. ACL, Command |
|
610 */ |
|
611 { |
|
612 TInt err = KErrNone; |
|
613 LOG_FUNC |
|
614 |
|
615 #ifdef _DEBUG_WINDOW |
|
616 LOG(_L8("Adding Frame to Reliable Queue")); |
|
617 LOGHEXDESC(aData); |
|
618 #endif |
|
619 |
|
620 CTxHctlBcspFrame *frame=iReliableQueue->WriteFrame(); |
|
621 |
|
622 // A NULL frame is now returned if (on the rare occasion) the frame queue has become blocked. |
|
623 // The original panic has been replaced by an upward error handling path. |
|
624 if (!frame) |
|
625 { |
|
626 err = KErrOverflow; |
|
627 } |
|
628 else |
|
629 { |
|
630 frame->SetProtocolId(aProtocolId); |
|
631 frame->SetPayload(aData); |
|
632 iSequencer->WakeUp(); |
|
633 } |
|
634 |
|
635 CanSend(); |
|
636 return err; |
|
637 |
|
638 } |
|
639 |
|
640 void CHCTLBcspFrameQueue::AddUnreliableFrame(const TDesC8 &aData, TUint8 aProtocolId, |
|
641 TUint8 aAck, |
|
642 TBool aCRCEnabled) |
|
643 /** |
|
644 Method to add an Unreliable frame to the unreliable frame queue |
|
645 |
|
646 @param aData - HCI payload |
|
647 @param aProtocolId |
|
648 @param aAck |
|
649 @param aCRCState |
|
650 |
|
651 Calls wakeup method on the sequencer to trigger frame sending |
|
652 */ |
|
653 { |
|
654 LOG_FUNC |
|
655 |
|
656 CTxHctlBcspFrame *frame=iUnreliableQueue->WriteFrame(); |
|
657 |
|
658 #ifdef _DEBUG_WINDOW |
|
659 LOG(_L8("Adding Frame to Unreliable Queue")); |
|
660 #endif |
|
661 |
|
662 LOGHEXDESC(aData); |
|
663 if ( frame ) |
|
664 { |
|
665 frame->SetProtocolId(aProtocolId); |
|
666 frame->SetPayload(aData); |
|
667 frame->SetFlags(aAck, aCRCEnabled, EFalse); |
|
668 } |
|
669 // else we've got no free slots - therefore since this is an unreliable Frame we can |
|
670 // just throw it away |
|
671 |
|
672 iSequencer->WakeUp(); |
|
673 } |
|
674 |
|
675 void CHCTLBcspFrameQueue::AddUnreliableFrame(TUint8 aProtocolId, |
|
676 TUint8 aAck, |
|
677 TBool aCRCEnabled) |
|
678 /** |
|
679 Method to add an empty Unreliable frame to the unreliable frame queue |
|
680 eg. an AckFrame |
|
681 |
|
682 @param aProtocolId |
|
683 @param aAck |
|
684 @param aCRCState |
|
685 |
|
686 */ |
|
687 { |
|
688 LOG_FUNC |
|
689 |
|
690 CTxHctlBcspFrame *frame=iUnreliableQueue->WriteFrame(); |
|
691 |
|
692 #ifdef _DEBUG_WINDOW |
|
693 LOG(_L8("Adding Empty Frame to Unreliable Queue")); |
|
694 #endif |
|
695 |
|
696 if ( frame ) |
|
697 { |
|
698 frame->SetProtocolId(aProtocolId); |
|
699 frame->SetPayload(); |
|
700 frame->SetFlags(aAck, aCRCEnabled, EFalse); |
|
701 } |
|
702 // else we've got no free slots - therefore since this is an unreliable Frame we can |
|
703 // just throw it away |
|
704 |
|
705 iSequencer->WakeUp(); |
|
706 |
|
707 } |
|
708 |
|
709 void CHCTLBcspFrameQueue::Reset() |
|
710 { |
|
711 LOG_FUNC |
|
712 |
|
713 iReliableQueue->Reset(); |
|
714 iUnreliableQueue->Reset(); |
|
715 } |
|
716 |
|
717 void CHCTLBcspFrameQueue::CanSend() |
|
718 /** |
|
719 Kicks packet router |
|
720 Only reliable queue is checked here for availability because we don't want to flow control |
|
721 the unreliable packets. Unreliable packets are simply dropped when the queue is full. |
|
722 */ |
|
723 { |
|
724 LOG_FUNC |
|
725 |
|
726 iBcsp.CanSend(iReliableQueue->FreeFrames()>0); |
|
727 } |