|
1 // Copyright (c) 1999-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 #include <bluetooth/logger.h> |
|
17 #include <es_sock.h> |
|
18 #include "rfcommframe.h" |
|
19 #include "rfcommmuxer.h" |
|
20 #include "rfcommconsts.h" |
|
21 #include "rfcommutil.h" |
|
22 #include "rfcommfcs.h" |
|
23 |
|
24 #ifdef __FLOG_ACTIVE |
|
25 _LIT8(KLogComponent, LOG_COMPONENT_RFCOMM); |
|
26 #endif |
|
27 |
|
28 CRfcommFrame::~CRfcommFrame() |
|
29 { |
|
30 iLink.Deque(); |
|
31 } |
|
32 |
|
33 /* |
|
34 CRfcommCtrlFrame is used for SABM, UA, DISC & DM frames |
|
35 */ |
|
36 |
|
37 CRfcommCtrlFrame::CRfcommCtrlFrame(CRfcommMuxer& aMux, CRfcommSAP* aSAP) |
|
38 : CRfcommFrame(aMux, aSAP), |
|
39 iData(KRfcommCtrlFrameSize) |
|
40 { |
|
41 LOG3(_L("RFCOMM: Ctrl Frame 0x%08x created, sap 0x%08x, len %d"), |
|
42 this, aSAP, iData.Length()); |
|
43 } |
|
44 |
|
45 CRfcommCtrlFrame::CRfcommCtrlFrame(CRfcommMuxer& aMux) |
|
46 : CRfcommFrame(aMux), |
|
47 iData(KRfcommCtrlFrameSize) |
|
48 { |
|
49 } |
|
50 |
|
51 CRfcommCtrlFrame::~CRfcommCtrlFrame() |
|
52 { |
|
53 DequeTimer(); |
|
54 } |
|
55 |
|
56 TBool CRfcommCtrlFrame::ResponseNeeded() |
|
57 { |
|
58 return iResponseNeeded; |
|
59 } |
|
60 |
|
61 void CRfcommCtrlFrame::QueResponseTimer() |
|
62 { |
|
63 if(iResponseNeeded && !iTimerQueued) |
|
64 { |
|
65 // Enque this timer |
|
66 TCallBack cb(TimerExpired, this); |
|
67 iTimerEntry.Set(cb); |
|
68 // Timer length dependent on whether this is a SABM for a DLCI other than 0 |
|
69 BTSocketTimer::Queue( |
|
70 ( ((iCtrl&~KPollFinalBitmask)==KSABMCtrlField) && ((iAddr>>2)!=KMuxDLCI) |
|
71 ?KFrameTimerT1SABM:KFrameTimerT1), iTimerEntry); |
|
72 iTimerQueued=ETrue; |
|
73 } |
|
74 } |
|
75 |
|
76 void CRfcommCtrlFrame::DequeTimer() |
|
77 { |
|
78 if(iTimerQueued) |
|
79 { |
|
80 BTSocketTimer::Remove(iTimerEntry); |
|
81 iTimerQueued=EFalse; |
|
82 } |
|
83 } |
|
84 |
|
85 TBool CRfcommCtrlFrame::Priority() const |
|
86 /** |
|
87 Check whether this RfcommCtrlFrame should |
|
88 a) jump past the data frames in the queue and |
|
89 b) be blocked by FCON/FCOFF flow control. |
|
90 |
|
91 If the function returns true, the frame will jump and |
|
92 not be affected by flow control. |
|
93 **/ |
|
94 { |
|
95 //FC ? |
|
96 switch(iCtrl) |
|
97 { |
|
98 case KUIHCBFCCtrlField: |
|
99 if(!DataLength()) |
|
100 return ETrue; |
|
101 default: |
|
102 break; |
|
103 } |
|
104 switch(iCtrl&~KPollFinalBitmask) |
|
105 { |
|
106 // |
|
107 case KUACtrlField: |
|
108 // Deliberate fall through... |
|
109 case KDMCtrlField: |
|
110 // High priority for UAs and DMs |
|
111 return ETrue; |
|
112 default: |
|
113 // Others (i.e. SABMs and DISCs) obey flow control. |
|
114 return EFalse; |
|
115 } |
|
116 // |
|
117 } |
|
118 |
|
119 TInt CRfcommCtrlFrame::TimerExpired(TAny* aFrame) |
|
120 /** |
|
121 The T1 timer on a ctrl frame has expired |
|
122 |
|
123 This is probably fatal to the mux, and certainly fatal |
|
124 for any SAP associated with frame. |
|
125 **/ |
|
126 { |
|
127 CRfcommCtrlFrame* frm=static_cast<CRfcommCtrlFrame*>(aFrame); |
|
128 // Notify the mux that this frame has timed out |
|
129 LOG2(_L("RFCOMM: Ctrl frame timeout, frame %08x, ctrl %d"), |
|
130 frm, frm->Ctrl()); |
|
131 |
|
132 frm->iTimerQueued=EFalse; |
|
133 frm->iMuxer.FrameResponseTimeout(frm); |
|
134 return EFalse; |
|
135 } |
|
136 |
|
137 |
|
138 void CRfcommCtrlFrame::SetResponseNeeded(TBool aNeed) |
|
139 { |
|
140 iResponseNeeded=aNeed; |
|
141 } |
|
142 |
|
143 const TDesC8& CRfcommCtrlFrame::Data() |
|
144 /** |
|
145 Returns a reference to the data. |
|
146 |
|
147 This function first builds up the data buffer, then sets the length |
|
148 and the FCS before returning the reference. |
|
149 **/ |
|
150 { |
|
151 __ASSERT_DEBUG(iCtrl != KUIHCtrlField, Panic(ERfcommBadFrameCtrlField)); |
|
152 __ASSERT_DEBUG(iData.Length()>=4, Panic(ERfcommBadFrameCtrlField)); |
|
153 LOG1(_L("CRfcommCtrlFrame::Data() - formatting data, length %d"), iData.Length()); |
|
154 iData[0]=iAddr; |
|
155 iData[1]=iCtrl; |
|
156 iData[2]=KRfcommCtrlFrameLengthByte; |
|
157 iData[3]=CalcFCS(iData.Ptr(), 3); // Calc over all three bytes |
|
158 return iData; |
|
159 } |
|
160 |
|
161 TInt CRfcommCtrlFrame::Type() const //Shehla - added for ease of Blogging |
|
162 /** |
|
163 Returns the typeid for this class |
|
164 **/ |
|
165 { |
|
166 return KCtrlFrameType; |
|
167 } |
|
168 |
|
169 /* |
|
170 CRfcommUIHFrame is used for all UIH data frames flowing over the link |
|
171 */ |
|
172 |
|
173 CRfcommUIHFrame* CRfcommUIHFrame::NewL(TInt aInformationLength, CRfcommMuxer& aMux, CRfcommSAP* aSAP) |
|
174 { |
|
175 CRfcommUIHFrame* self=new(ELeave) CRfcommUIHFrame( aMux, aSAP); |
|
176 CleanupStack::PushL(self); |
|
177 self->ConstructDataBufferL(aInformationLength); |
|
178 CleanupStack::Pop(); // self |
|
179 LOG2(_L("RFCOMM: Data Frame 0x%08x created, sap 0x%08x"), self, aSAP); |
|
180 return self; |
|
181 } |
|
182 |
|
183 CRfcommUIHFrame::CRfcommUIHFrame(CRfcommMuxer& aMux, CRfcommSAP* aSAP) |
|
184 : CRfcommFrame(aMux, aSAP) |
|
185 { |
|
186 } |
|
187 |
|
188 CRfcommUIHFrame::~CRfcommUIHFrame() |
|
189 { |
|
190 delete iData; |
|
191 } |
|
192 |
|
193 void CRfcommUIHFrame::ConstructDataBufferL(TInt aInformationLength) |
|
194 /** |
|
195 Allocate the data buffer to hold the information that will be placed in this frame. |
|
196 |
|
197 An allowance is made for the KMaxFrameHeaderLength, ie. addr, ctrl , 2*len = 4 octets |
|
198 **/ |
|
199 { |
|
200 iData=HBufC8::NewL(aInformationLength+KMaxFrameOverhead); |
|
201 // Reserve max possible space for addr, control, length, and fcs at end |
|
202 for(TUint8 i=0;i<KMaxFrameOverhead-1;++i) |
|
203 PutByte(0x00); |
|
204 } |
|
205 |
|
206 TInt CRfcommUIHFrame::Type() const |
|
207 { |
|
208 return KDataFrameType; |
|
209 } |
|
210 |
|
211 TBool CRfcommUIHFrame::ResponseNeeded() |
|
212 { |
|
213 return EFalse; |
|
214 } |
|
215 |
|
216 void CRfcommUIHFrame::QueResponseTimer() |
|
217 /** |
|
218 Never a response for data frames, so do nothing |
|
219 **/ |
|
220 { |
|
221 // Nothing |
|
222 } |
|
223 |
|
224 void CRfcommUIHFrame::DequeTimer() |
|
225 { |
|
226 // Do nothing |
|
227 } |
|
228 |
|
229 TBool CRfcommUIHFrame::Priority() const |
|
230 { |
|
231 return EFalse; |
|
232 } |
|
233 |
|
234 TUint16 CRfcommUIHFrame::DataLength() const |
|
235 { |
|
236 TInt overhead = iFramePrepared?KMaxFrameOverhead:KMaxFrameHeaderLength; |
|
237 TUint16 length=static_cast<TUint16>((*iData).Length()-overhead); |
|
238 return length; |
|
239 } |
|
240 |
|
241 void CRfcommUIHFrame::PutByte(TUint8 aByte) |
|
242 { |
|
243 iData->Des().Append(aByte); |
|
244 } |
|
245 |
|
246 void CRfcommUIHFrame::PutLittleEndian16(TUint16 aVal) |
|
247 { |
|
248 TUint8* ptr=const_cast<TUint8*>((*iData).Ptr()); |
|
249 ptr+=(*iData).Length(); |
|
250 iData->Des().SetLength((*iData).Length()+2); |
|
251 LittleEndian::Put16(ptr, aVal); |
|
252 } |
|
253 |
|
254 void CRfcommUIHFrame::PutLittleEndian32(TUint32 aVal) |
|
255 { |
|
256 TUint8* ptr=const_cast<TUint8*>((*iData).Ptr()); |
|
257 ptr+=(*iData).Length(); |
|
258 iData->Des().SetLength((*iData).Length()+4); |
|
259 LittleEndian::Put32(ptr, aVal); |
|
260 } |
|
261 |
|
262 void CRfcommUIHFrame::PutData(const TDesC8& aDes) |
|
263 { |
|
264 iData->Des().Append(aDes); |
|
265 } |
|
266 |
|
267 const TDesC8& CRfcommUIHFrame::Data() |
|
268 /** |
|
269 Build the data frame, then return it |
|
270 |
|
271 **/ |
|
272 { |
|
273 if(!iFramePrepared) |
|
274 PrepareDataFrame(); |
|
275 return iReturnedFrame; |
|
276 } |
|
277 |
|
278 void CRfcommUIHFrame::PrepareDataFrame() |
|
279 /** |
|
280 Build the data frame and return it |
|
281 |
|
282 Fill in the address, ctrl and length fields, then add the FCS |
|
283 Don't do any asserts on the basic parts since this can be used |
|
284 by derived classes. |
|
285 |
|
286 An additional complication here is that the length field may |
|
287 be either 1 or 2 octets, depending on the length of the data |
|
288 field. |
|
289 **/ |
|
290 { |
|
291 //TUint length=static_cast<TUint16>((*iData).Length()-KMaxFrameHeaderLength); |
|
292 TUint length = DataLength(); |
|
293 TPtr8 rwData=iData->Des(); |
|
294 TInt offset=0; |
|
295 if(length<=127) |
|
296 { |
|
297 // Note the length dependent offset for the Address and Control Octets |
|
298 offset=1; |
|
299 // length will be just the 4th octet in the buffer, |
|
300 // of which we will return everything from the |
|
301 // second octet onwards... |
|
302 rwData[3]=static_cast<TUint8>(length<<1 | 1); // Set the E/A bit to 1 |
|
303 } |
|
304 else |
|
305 { |
|
306 // length will be in both the 3rd and 4th octet in the buffer. |
|
307 // length is stored as follows; |
|
308 // |
|
309 // Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8 |
|
310 // Octet 1 E/A L1 L2 L3 L4 L5 L6 L7 |
|
311 // Octet 2 L8 L9 L10 L11 L12 L13 L14 L15 |
|
312 offset=0; |
|
313 rwData[2]=static_cast<TUint8>((length & 0x7F)<<1); |
|
314 rwData[3]=static_cast<TUint8>((length>>7) & 0xFF); |
|
315 } |
|
316 |
|
317 rwData[offset]=iAddr; |
|
318 rwData[1+offset]=KUIHCtrlField; |
|
319 rwData.Append(CalcFCS((*iData).Ptr()+offset, 2)); // Calc over two bytes |
|
320 iReturnedFrame.Set((*iData).Right((*iData).Length()-offset)); |
|
321 iFramePrepared=ETrue; |
|
322 } |
|
323 |
|
324 void CRfcommUIHFrame::PutByteAt(TInt aOffset, TUint8 aByte) |
|
325 /** |
|
326 Insert this byte in the data part of the packet at the |
|
327 position specified |
|
328 |
|
329 @param aOffset The index into the data part of the packet |
|
330 (after the length field) |
|
331 **/ |
|
332 { |
|
333 (iData->Des())[KMaxFrameHeaderLength+aOffset]=aByte; |
|
334 } |
|
335 |
|
336 |
|
337 |
|
338 |
|
339 |
|
340 |
|
341 /* |
|
342 CRfcommDataFrame is used for UIH data frames designed to carry information |
|
343 */ |
|
344 |
|
345 CRfcommDataFrame* CRfcommDataFrame::NewL(TInt aInformationLength, CRfcommMuxer& aMux, CRfcommSAP* aSAP) |
|
346 { |
|
347 CRfcommDataFrame* self=new(ELeave) CRfcommDataFrame( aMux, aSAP); |
|
348 CleanupStack::PushL(self); |
|
349 self->ConstructDataBufferL(aInformationLength); |
|
350 CleanupStack::Pop(); // self |
|
351 LOG2(_L("RFCOMM: Data Frame 0x%08x created, sap 0x%08x"), self, aSAP); |
|
352 return self; |
|
353 } |
|
354 |
|
355 CRfcommDataFrame::CRfcommDataFrame(CRfcommMuxer& aMux, CRfcommSAP* aSAP) |
|
356 : CRfcommUIHFrame(aMux, aSAP) |
|
357 { |
|
358 } |
|
359 |
|
360 CRfcommDataFrame::~CRfcommDataFrame() |
|
361 { |
|
362 } |
|
363 |
|
364 |
|
365 void CRfcommDataFrame::ConstructDataBufferL(TInt aInformationLength) |
|
366 /** |
|
367 Allocate the data buffer to hold the information that will be placed in this frame. |
|
368 |
|
369 An allowance is made for the KMaxFrameHeaderLength, ie. addr, ctrl , 2*len = 4 octets |
|
370 **/ |
|
371 { |
|
372 // Reserve max possible space for addr, cont, length |
|
373 iData=HBufC8::NewL(aInformationLength+KMaxFrameOverhead); |
|
374 for(TUint8 i=0;i<KMaxFrameOverhead-1;++i) |
|
375 PutByte(0x00); |
|
376 } |
|
377 |
|
378 void CRfcommDataFrame::PrepareDataFrame() |
|
379 /** |
|
380 Build the data frame and return it |
|
381 |
|
382 Fill in the address, ctrl and length fields, then add the FCS |
|
383 Don't do any asserts on the basic parts since this can be used |
|
384 by derived classes. |
|
385 |
|
386 An additional complication here is that the length field may |
|
387 be either 1 or 2 octets, depending on the length of the data |
|
388 field. |
|
389 **/ |
|
390 { |
|
391 //TUint length=static_cast<TUint16>((*iData).Length()-KMaxFrameHeaderLength); |
|
392 TUint length = DataLength(); |
|
393 TPtr8 rwData=iData->Des(); |
|
394 TInt offset=0; |
|
395 if(length<=127) |
|
396 { |
|
397 // Note the length dependent offset for the Address and Control Octets |
|
398 offset=1; |
|
399 // length will be just the 4th octet in the buffer, |
|
400 // of which we will return everything from the |
|
401 // second octet onwards... |
|
402 rwData[3]=static_cast<TUint8>(length<<1 | 1); // Set the E/A bit to 1 |
|
403 } |
|
404 else |
|
405 { |
|
406 // length will be in both the 3rd and 4th octet in the buffer. |
|
407 // length is stored as follows; |
|
408 // |
|
409 // Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8 |
|
410 // Octet 1 E/A L1 L2 L3 L4 L5 L6 L7 |
|
411 // Octet 2 L8 L9 L10 L11 L12 L13 L14 L15 |
|
412 offset=0; |
|
413 rwData[2]=static_cast<TUint8>((length & 0x7F)<<1); |
|
414 rwData[3]=static_cast<TUint8>((length>>7) & 0xFF); |
|
415 } |
|
416 |
|
417 rwData[offset]=iAddr; |
|
418 rwData[1+offset]=KUIHCtrlField; |
|
419 rwData.Append(CalcFCS((*iData).Ptr()+offset, 2)); // Calc over two bytes |
|
420 iReturnedFrame.Set((*iData).Right((*iData).Length()-offset)); |
|
421 iFramePrepared=ETrue; |
|
422 } |
|
423 |
|
424 |
|
425 |
|
426 |
|
427 /* |
|
428 CRfcommCreditDataFrame is used for UIH data frames designed to carry information and supply credits |
|
429 */ |
|
430 |
|
431 CRfcommCreditDataFrame* CRfcommCreditDataFrame::NewL(TInt aInformationLength, CRfcommMuxer& aMux, CRfcommSAP* aSAP) |
|
432 { |
|
433 CRfcommCreditDataFrame* self=new(ELeave) CRfcommCreditDataFrame( aMux, aSAP); |
|
434 CleanupStack::PushL(self); |
|
435 self->ConstructDataBufferL(aInformationLength); |
|
436 CleanupStack::Pop(); // self |
|
437 LOG2(_L("RFCOMM: Data Frame 0x%08x created, sap 0x%08x"), self, aSAP); |
|
438 return self; |
|
439 } |
|
440 |
|
441 CRfcommCreditDataFrame::CRfcommCreditDataFrame(CRfcommMuxer& aMux, CRfcommSAP* aSAP) |
|
442 : CRfcommDataFrame(aMux, aSAP) |
|
443 { |
|
444 } |
|
445 |
|
446 CRfcommCreditDataFrame::~CRfcommCreditDataFrame() |
|
447 { |
|
448 } |
|
449 |
|
450 TInt CRfcommCreditDataFrame::Type() const |
|
451 { |
|
452 return KCreditDataFrameType; |
|
453 } |
|
454 |
|
455 void CRfcommCreditDataFrame::SetCredit(TUint8 aCredit) |
|
456 /** |
|
457 Add the credit to an outgoing UIH frame |
|
458 **/ |
|
459 { |
|
460 iCredit = aCredit; |
|
461 } |
|
462 |
|
463 TUint8 CRfcommCreditDataFrame::Credit() const |
|
464 { |
|
465 return iCredit; |
|
466 } |
|
467 |
|
468 |
|
469 TUint16 CRfcommCreditDataFrame::DataLength() const |
|
470 { |
|
471 TInt overhead = iFramePrepared?KMaxFrameCreditOverhead:KMaxCreditFrameHeaderLength; |
|
472 TUint16 length=static_cast<TUint16>((*iData).Length()-overhead); |
|
473 return length; |
|
474 } |
|
475 |
|
476 void CRfcommCreditDataFrame::ConstructDataBufferL(TInt aInformationLength) |
|
477 /** |
|
478 Allocate the data buffer to hold the information that will be placed in this frame. |
|
479 |
|
480 An allowance is made for the KMaxFrameHeaderLength, ie. addr, ctrl, 2*len, credit = 5 octets |
|
481 **/ |
|
482 { |
|
483 // Reserve max possible space for addr, cont, length |
|
484 iData=HBufC8::NewL(aInformationLength+KMaxFrameCreditOverhead); |
|
485 for(TUint8 i=0;i<KMaxFrameCreditOverhead-1;++i) |
|
486 PutByte(0x00); |
|
487 } |
|
488 |
|
489 void CRfcommCreditDataFrame::PrepareDataFrame() |
|
490 /** |
|
491 Build the data frame and return it |
|
492 |
|
493 Fill in the address, ctrl and length fields, then add the FCS |
|
494 Don't do any asserts on the basic parts since this can be used |
|
495 by derived classes. |
|
496 |
|
497 An additional complication here is that the length field may |
|
498 be either 1 or 2 octets, depending on the length of the data |
|
499 field. |
|
500 **/ |
|
501 { |
|
502 //TUint length=static_cast<TUint16>((*iData).Length()-KMaxCreditFrameHeaderLength); |
|
503 TUint length = DataLength(); |
|
504 TPtr8 rwData=iData->Des(); |
|
505 TInt offset=0; |
|
506 rwData[4]=iCredit; // we're going backwards, credit is after length |
|
507 if(length<=127) |
|
508 { |
|
509 // Note the length dependent offset for the Address and Control Octets |
|
510 offset=1; |
|
511 // length will be just the 4th octet in the buffer, |
|
512 // of which we will return everything from the |
|
513 // second octet onwards... |
|
514 rwData[3]=static_cast<TUint8>(length<<1 | 1); // Set the E/A bit to 1 |
|
515 } |
|
516 else |
|
517 { |
|
518 // length will be in both the 3rd and 4th octet in the buffer. |
|
519 // length is stored as follows; |
|
520 // |
|
521 // Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8 |
|
522 // Octet 1 E/A L1 L2 L3 L4 L5 L6 L7 |
|
523 // Octet 2 L8 L9 L10 L11 L12 L13 L14 L15 |
|
524 offset=0; |
|
525 rwData[2]=static_cast<TUint8>((length & 0x7F)<<1); |
|
526 rwData[3]=static_cast<TUint8>((length>>7) & 0xFF); |
|
527 } |
|
528 |
|
529 rwData[offset]=iAddr; |
|
530 rwData[1+offset]=KUIHCBFCCtrlField; |
|
531 rwData.Append(CalcFCS((*iData).Ptr()+offset, 2)); // Calc over two bytes |
|
532 iReturnedFrame.Set((*iData).Right((*iData).Length()-offset)); |
|
533 iFramePrepared=ETrue; |
|
534 } |
|
535 |
|
536 |
|
537 |
|
538 /* |
|
539 CRfcommMuxCtrlFrame is used for frames carrying mux control |
|
540 commands on the mux control channel (DLCI 0) |
|
541 */ |
|
542 |
|
543 CRfcommMuxCtrlFrame* CRfcommMuxCtrlFrame::NewL(TUint8 aCommandValuesLength, CRfcommMuxer& aMux, CRfcommSAP* aSAP) |
|
544 { |
|
545 CRfcommMuxCtrlFrame* self=new(ELeave) CRfcommMuxCtrlFrame(aCommandValuesLength, aMux, aSAP); |
|
546 CleanupStack::PushL(self); |
|
547 self->ConstructDataBufferL(aCommandValuesLength); |
|
548 CleanupStack::Pop(); // self |
|
549 LOG2(_L("RFCOMM: Mux Ctrl Frame 0x%08x created, sap 0x%08x"), self, aSAP); |
|
550 |
|
551 return self; |
|
552 } |
|
553 |
|
554 void CRfcommMuxCtrlFrame::ConstructDataBufferL(TInt aCommandValuesLength) |
|
555 /** |
|
556 Allocate the data buffer to hold the command that will be |
|
557 placed in this frame. |
|
558 |
|
559 This function takes the number of value octets required by the |
|
560 command and adds on the appropriate number of octets to allow |
|
561 for the type and length fields |
|
562 **/ |
|
563 { |
|
564 CRfcommUIHFrame::ConstructDataBufferL(aCommandValuesLength+KShortMuxCommandHeaderLength); |
|
565 // Reserve space for command type and command length |
|
566 for(TUint8 i=0;i<KShortMuxCommandHeaderLength;++i) |
|
567 PutByte(0x00); |
|
568 } |
|
569 |
|
570 |
|
571 CRfcommMuxCtrlFrame::CRfcommMuxCtrlFrame(TUint8 aCommandValuesLength, CRfcommMuxer& aMux, CRfcommSAP* aSAP) |
|
572 : CRfcommUIHFrame(aMux, aSAP), |
|
573 iCommandLength(aCommandValuesLength) |
|
574 { |
|
575 } |
|
576 |
|
577 CRfcommMuxCtrlFrame::~CRfcommMuxCtrlFrame() |
|
578 { |
|
579 if(iTimerQueued) |
|
580 BTSocketTimer::Remove(iTimerEntry); |
|
581 } |
|
582 |
|
583 TInt CRfcommMuxCtrlFrame::Type() const |
|
584 { |
|
585 return KMuxCtrlFrameType; |
|
586 } |
|
587 |
|
588 void CRfcommMuxCtrlFrame::SetResponseNeeded(TBool aNeed) |
|
589 { |
|
590 iResponseNeeded=aNeed; |
|
591 } |
|
592 |
|
593 TBool CRfcommMuxCtrlFrame::ResponseNeeded() |
|
594 { |
|
595 return iResponseNeeded; |
|
596 } |
|
597 |
|
598 void CRfcommMuxCtrlFrame::QueResponseTimer() |
|
599 /* |
|
600 Que a timer if necessary |
|
601 */ |
|
602 { |
|
603 if(iResponseNeeded && !iTimerQueued) |
|
604 { |
|
605 // Enque this timer |
|
606 TCallBack cb(TimerExpired, this); |
|
607 iTimerEntry.Set(cb); |
|
608 BTSocketTimer::Queue(KFrameTimerT2, iTimerEntry); |
|
609 iTimerQueued=ETrue; |
|
610 } |
|
611 } |
|
612 |
|
613 void CRfcommMuxCtrlFrame::DequeTimer() |
|
614 { |
|
615 if(iTimerQueued) |
|
616 { |
|
617 BTSocketTimer::Remove(iTimerEntry); |
|
618 iTimerQueued=EFalse; |
|
619 } |
|
620 } |
|
621 |
|
622 TBool CRfcommMuxCtrlFrame::Priority() const |
|
623 { |
|
624 return ETrue; |
|
625 } |
|
626 |
|
627 TInt CRfcommMuxCtrlFrame::TimerExpired(TAny* aFrame) |
|
628 { |
|
629 CRfcommMuxCtrlFrame* frm=static_cast<CRfcommMuxCtrlFrame*>(aFrame); |
|
630 // Notify the mux that this frame has timed out |
|
631 LOG2(_L("RFCOMM: MuxCtrl frame timeout, frame %08x, command %d"), |
|
632 frm, frm->CommandType()); |
|
633 /* |
|
634 BLOG: Timeout on command: |
|
635 TUint8 command = frm->CommandType(); |
|
636 switch(command) |
|
637 { |
|
638 case KTestType |
|
639 //KBlogTestCommand |
|
640 break; |
|
641 case KPNType |
|
642 //KBlogPN |
|
643 break; |
|
644 case KRPNType |
|
645 //KBlogRPN |
|
646 break; |
|
647 case KFConType |
|
648 //KBlogFcOn |
|
649 break; |
|
650 case KFCoffType |
|
651 //KBlogFcOff |
|
652 break; |
|
653 case KMSCType |
|
654 //KBlogMSC |
|
655 break; |
|
656 case KNSCType |
|
657 //KBlogNSC |
|
658 break; |
|
659 case KRLSType |
|
660 //KBlogRLS |
|
661 break; |
|
662 }; |
|
663 |
|
664 //BLOG: MuxCtrl frame timeout, |
|
665 */ |
|
666 |
|
667 frm->iTimerQueued=EFalse; |
|
668 frm->iMuxer.FrameResponseTimeout(frm); |
|
669 return EFalse; |
|
670 } |
|
671 |
|
672 |
|
673 #pragma warning(disable : 4244) // conversion from int to unsigned char |
|
674 |
|
675 void CRfcommMuxCtrlFrame::SetCommandType(TUint8 aType, TBool aCommand) |
|
676 { |
|
677 iCommandType=(aType << 1) | (aCommand ? 1 : 0); |
|
678 } |
|
679 |
|
680 TUint8 CRfcommMuxCtrlFrame::CommandType() const |
|
681 { |
|
682 return iCommandType >> 1; |
|
683 } |
|
684 |
|
685 void CRfcommMuxCtrlFrame::PrepareDataFrame() |
|
686 /** |
|
687 Prepare the Mux ctrl frame to be transmitted. |
|
688 |
|
689 We add the command type, command length before using the normal |
|
690 UIH frame PrepareDataFrame to add the normal headers+FCS |
|
691 **/ |
|
692 { |
|
693 __ASSERT_DEBUG((iAddr & 0xfc) == 0, Panic(ERfcommBadFrameAddrField)); |
|
694 __ASSERT_DEBUG(iCtrl == KUIHCtrlField, Panic(ERfcommBadFrameCtrlField)); |
|
695 TUint8 byte; |
|
696 byte= (iCommandType << 1) | 0x01; // add EA bit |
|
697 PutByteAt(0, byte); |
|
698 byte=(iCommandLength << 1) | 0x01; // add EA bit |
|
699 PutByteAt(1, byte); |
|
700 CRfcommUIHFrame::PrepareDataFrame(); |
|
701 } |
|
702 |
|
703 #pragma warning(default : 4244) |