|
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 "hctlbcspframe.h" |
|
22 |
|
23 #include "bcsputils.h" |
|
24 #include "hctlbcspconsts.h" |
|
25 #include "debug.h" |
|
26 |
|
27 const TUint16 KCrcTable[] = |
|
28 /** |
|
29 Global CRC table |
|
30 */ |
|
31 { |
|
32 0x0000, 0x1081, 0x2102, 0x3183, |
|
33 0x4204, 0x5285, 0x6306, 0x7387, |
|
34 0x8408, 0x9489, 0xa50a, 0xb58b, |
|
35 0xc60c, 0xd68d, 0xe70e, 0xf78f |
|
36 }; |
|
37 |
|
38 /** |
|
39 Implementation of Class THctlBcspPacketType |
|
40 */ |
|
41 |
|
42 |
|
43 /** |
|
44 Method to set BCSP ProtocolId |
|
45 */ |
|
46 TInt THCTLBcspPacketType::SetProtocolId(TUint8 aProtocolId) |
|
47 { |
|
48 LOG_FUNC |
|
49 |
|
50 #ifdef __ARMCC__ |
|
51 // Suppressing the warning "Pointless comparison of unsigned integer with zero" |
|
52 // as although a constant may be zero it is present so as to make the code more |
|
53 // understandable. |
|
54 # pragma diag_suppress 186 |
|
55 #endif // __ARMCC__ |
|
56 |
|
57 // if (>2 && <5 || >7) then fail |
|
58 if ((aProtocolId > KBcspBcCmdChnl && aProtocolId < KBcspCommEvntChnl) || (aProtocolId > KBcspSynchronousDataChnl)) |
|
59 { |
|
60 LOG1(_L8("THCTLBcspPacketType: Header unsupported, this used to be a BCSP 6 panic, now error handled. aProtocolId = %d"), aProtocolId); |
|
61 return KErrNotSupported; |
|
62 } |
|
63 |
|
64 #ifdef __ARMCC__ |
|
65 # pragma diag_default 186 |
|
66 #endif // __ARMCC__ |
|
67 |
|
68 iProtocolId = aProtocolId; |
|
69 return KErrNone; |
|
70 } |
|
71 |
|
72 TUint8 THCTLBcspPacketType::ProtocolId() const |
|
73 { |
|
74 return iProtocolId; |
|
75 } |
|
76 |
|
77 /** |
|
78 Implementation of Class THctlBcspFlags |
|
79 */ |
|
80 |
|
81 TBool THCTLBcspFlags::CrcEnabled() const |
|
82 { |
|
83 return (iFlagsField & KBcspCrcPresentMask); |
|
84 } |
|
85 |
|
86 TUint8 THCTLBcspFlags::Ack() const |
|
87 { |
|
88 return ((iFlagsField & KBcspAckMask) >> KBcspAckFieldOffset); |
|
89 } |
|
90 |
|
91 TUint8 THCTLBcspFlags::Sequence() const |
|
92 { |
|
93 return (iFlagsField & KBcspSeqMask); |
|
94 } |
|
95 |
|
96 TBool THCTLBcspFlags::IsReliableProtcolType() const |
|
97 { |
|
98 return (iFlagsField & KBcspProtocolTypeMask); |
|
99 } |
|
100 |
|
101 TUint8 THCTLBcspFlags::FlagsField() const |
|
102 { |
|
103 return iFlagsField; |
|
104 } |
|
105 |
|
106 /** |
|
107 Trivial setter will panic if we attempt to set an invalid value |
|
108 */ |
|
109 void THCTLBcspFlags::SetAck(TUint8 aValue) |
|
110 { |
|
111 __ASSERT_DEBUG((aValue < KMaxWindowSize), PANIC(KBcspPanicCat, EBcspInvalidAckValue)); |
|
112 // Clear the existing value and set the new value. |
|
113 iFlagsField &= ~KBcspAckMask; |
|
114 iFlagsField |= (aValue << KBcspAckFieldOffset); |
|
115 } |
|
116 |
|
117 /** |
|
118 Trivial setter will panic if we attempt to set an invalid value |
|
119 */ |
|
120 void THCTLBcspFlags::SetSequence(TUint8 aSeq) |
|
121 { |
|
122 __ASSERT_DEBUG((aSeq < KMaxWindowSize), PANIC(KBcspPanicCat, EBcspInvalidSequenceValue)); |
|
123 iFlagsField &= ~KBcspSeqMask; |
|
124 iFlagsField |= aSeq; |
|
125 } |
|
126 |
|
127 /** |
|
128 Trivial setter |
|
129 */ |
|
130 void THCTLBcspFlags::SetCrcEnabled(TBool aCrcEnabled) |
|
131 { |
|
132 if(aCrcEnabled) |
|
133 { |
|
134 iFlagsField |= KBcspCrcPresentMask; |
|
135 } |
|
136 else |
|
137 { |
|
138 iFlagsField &= ~KBcspCrcPresentMask; |
|
139 } |
|
140 } |
|
141 |
|
142 void THCTLBcspFlags::SetIsReliableProtcolType(TBool aIsReliableProtcolType) |
|
143 { |
|
144 if(aIsReliableProtcolType) |
|
145 { |
|
146 iFlagsField |= KBcspProtocolTypeMask; |
|
147 } |
|
148 else |
|
149 { |
|
150 iFlagsField &= ~KBcspProtocolTypeMask; |
|
151 } |
|
152 } |
|
153 |
|
154 void THCTLBcspFlags::SetFlagsField(TUint8 aFlagsField) |
|
155 { |
|
156 iFlagsField = aFlagsField; |
|
157 } |
|
158 |
|
159 /** |
|
160 Implementation of Class CHCTLBcspFrame |
|
161 */ |
|
162 CHCTLBcspFrame::CHCTLBcspFrame() |
|
163 { |
|
164 } |
|
165 |
|
166 /** |
|
167 Method to set the flags in the Header byte of a BCSP frame |
|
168 */ |
|
169 void CHCTLBcspFrame::SetFlags(TUint8 aAck, TBool aIsCrcEnabled, TBool aIsReliableProtcolType) |
|
170 { |
|
171 LOG_FUNC |
|
172 iFlagHeaderByte.SetAck(aAck); |
|
173 iFlagHeaderByte.SetCrcEnabled(aIsCrcEnabled); |
|
174 iFlagHeaderByte.SetIsReliableProtcolType(aIsReliableProtcolType); |
|
175 } |
|
176 |
|
177 void CHCTLBcspFrame::SetSequence(TUint8 aSeq) |
|
178 { |
|
179 iFlagHeaderByte.SetSequence(aSeq); |
|
180 } |
|
181 |
|
182 TInt CHCTLBcspFrame::SetProtocolId(TUint8 aProtocolId) |
|
183 { |
|
184 return iProtocolId.SetProtocolId(aProtocolId); |
|
185 } |
|
186 |
|
187 TBool CHCTLBcspFrame::CrcEnabled() const |
|
188 { |
|
189 return iFlagHeaderByte.CrcEnabled(); |
|
190 } |
|
191 |
|
192 TUint8 CHCTLBcspFrame::CheckSum() const |
|
193 { |
|
194 return iCheckSum; |
|
195 } |
|
196 |
|
197 TUint8 CHCTLBcspFrame::ProtocolId() const |
|
198 { |
|
199 return iProtocolId.ProtocolId(); |
|
200 } |
|
201 |
|
202 TUint8 CHCTLBcspFrame::FlagsField() const |
|
203 { |
|
204 return iFlagHeaderByte.FlagsField(); |
|
205 } |
|
206 |
|
207 TUint16 CHCTLBcspFrame::PayloadLength() const |
|
208 { |
|
209 return static_cast<TUint16>(iPayloadPtr.Size()); |
|
210 } |
|
211 |
|
212 TInt CHCTLBcspFrame::ValidateChecksum(const TDesC8& aHeader) |
|
213 /** |
|
214 Method to validate the checksum of a received frame header |
|
215 */ |
|
216 { |
|
217 LOG_FUNC |
|
218 TInt rerr = KErrNone; |
|
219 |
|
220 if (aHeader.Length() < KBcspHeaderBytes) |
|
221 { |
|
222 rerr = KErrBcspHeaderCorrupt; |
|
223 } |
|
224 else if(aHeader[KBcspHeaderChecksumByteIndex] != CalcCheckSum(aHeader)) |
|
225 { |
|
226 rerr = KErrBcspHeaderCorrupt; |
|
227 } |
|
228 |
|
229 return rerr; |
|
230 } |
|
231 |
|
232 TDesC8& CHCTLBcspFrame::Payload() |
|
233 /** |
|
234 Trivial getter method |
|
235 */ |
|
236 { |
|
237 return iPayloadPtr; |
|
238 } |
|
239 |
|
240 TUint8 CHCTLBcspFrame::Sequence() const |
|
241 /** |
|
242 Trivial getter method |
|
243 */ |
|
244 { |
|
245 return iFlagHeaderByte.Sequence(); |
|
246 } |
|
247 |
|
248 TUint8 CHCTLBcspFrame::Ack() const |
|
249 /** |
|
250 Trivial getter method |
|
251 */ |
|
252 { |
|
253 return iFlagHeaderByte.Ack(); |
|
254 } |
|
255 |
|
256 TBool CHCTLBcspFrame::IsReliableProtcolType() const |
|
257 /** |
|
258 Trivial getter method |
|
259 */ |
|
260 { |
|
261 return iFlagHeaderByte.IsReliableProtcolType(); |
|
262 } |
|
263 |
|
264 TUint16 CHCTLBcspFrame::CalcCRC(const TDesC8& aData) |
|
265 /** |
|
266 @param aData - Parameters Buffer upon which to calculate crc |
|
267 @return CRC Value TUint16 |
|
268 */ |
|
269 { |
|
270 LOG_FUNC |
|
271 TUint16 crcValue = 0xffff; // Fill the shift register with 1s |
|
272 TUint8 dataByte; |
|
273 |
|
274 for (TInt i=0;i<aData.Length();i++) |
|
275 { |
|
276 dataByte = aData[i]; |
|
277 crcValue = static_cast<TUint16>((crcValue >> 4) ^ KCrcTable[(crcValue^dataByte) & 0xf]); |
|
278 crcValue = static_cast<TUint16>((crcValue >> 4) ^ KCrcTable[(crcValue^(dataByte >> 4)) & 0xf]); |
|
279 } |
|
280 return ReverseCrcBits(crcValue); // Reverse all the bits in the CRC |
|
281 } |
|
282 |
|
283 TUint16 CHCTLBcspFrame::ReverseCrcBits(TUint16 aCRCValue) |
|
284 /** |
|
285 Method to reverse the CRC Value |
|
286 @param aCRCValue |
|
287 */ |
|
288 { |
|
289 TUint16 result = 0; |
|
290 for(TInt b=0;b<16;b++) |
|
291 { |
|
292 result = static_cast<TUint16>(result << 1) ; |
|
293 result |= (aCRCValue & 1); |
|
294 aCRCValue = static_cast<TUint16>(aCRCValue >> 1); |
|
295 } |
|
296 return result; |
|
297 } |
|
298 |
|
299 |
|
300 |
|
301 TUint8 CHCTLBcspFrame::CalcCheckSum(const TDesC8& aHeader) |
|
302 /** |
|
303 Method to calculate the checksum |
|
304 The Checksum error is used to check the integrity of the header: |
|
305 */ |
|
306 { |
|
307 LOG_FUNC |
|
308 __ASSERT_DEBUG(aHeader.Length() >= KBcspHeaderBytes, PANIC(KBcspPanicCat, EBadBcspFrame)); |
|
309 TUint8 tempsum = static_cast <TUint8>(aHeader[KBcspHeaderFlagsByteIndex] + |
|
310 aHeader[KBcspHeaderByte2Index] + |
|
311 aHeader[KBcspHeaderByte3Index]); |
|
312 return ~tempsum; |
|
313 } |
|
314 |
|
315 void CHCTLBcspFrame::Reset() |
|
316 /** |
|
317 Method to reset the frame |
|
318 */ |
|
319 { |
|
320 LOG_FUNC |
|
321 iIsValid = EFalse; |
|
322 } |
|
323 |
|
324 TBool CHCTLBcspFrame::IsValid() const |
|
325 /** |
|
326 Trvial getter method |
|
327 */ |
|
328 { |
|
329 return iIsValid; |
|
330 } |
|
331 |
|
332 |
|
333 /** |
|
334 Implementation of Class CTxHctlBcspFrame |
|
335 */ |
|
336 |
|
337 CTxHctlBcspFrame* CTxHctlBcspFrame::NewLC(const TDesC8& aHCIPayload) |
|
338 { |
|
339 LOG_STATIC_FUNC |
|
340 CTxHctlBcspFrame* self= new(ELeave) CTxHctlBcspFrame(); |
|
341 CleanupStack::PushL(self); |
|
342 self->ConstructL(aHCIPayload); |
|
343 return self; |
|
344 } |
|
345 |
|
346 CTxHctlBcspFrame* CTxHctlBcspFrame::NewLC(TInt aFrameSize) |
|
347 { |
|
348 LOG_STATIC_FUNC |
|
349 CTxHctlBcspFrame* self= new(ELeave) CTxHctlBcspFrame(); |
|
350 CleanupStack::PushL(self); |
|
351 self->ConstructL(aFrameSize); |
|
352 return self; |
|
353 } |
|
354 |
|
355 CTxHctlBcspFrame* CTxHctlBcspFrame::NewL(const TDesC8& aHCIPayload) |
|
356 { |
|
357 LOG_STATIC_FUNC |
|
358 CTxHctlBcspFrame *self=NewLC(aHCIPayload); |
|
359 CleanupStack::Pop(self); |
|
360 return self; |
|
361 } |
|
362 |
|
363 CTxHctlBcspFrame* CTxHctlBcspFrame::NewL(TInt aFrameSize) |
|
364 { |
|
365 LOG_STATIC_FUNC |
|
366 CTxHctlBcspFrame *self=NewLC(aFrameSize); |
|
367 CleanupStack::Pop(self); |
|
368 return self; |
|
369 } |
|
370 |
|
371 void CTxHctlBcspFrame::ConstructL(const TDesC8& aHCIPayload) |
|
372 { |
|
373 LOG_FUNC |
|
374 |
|
375 // Instantiates iFrame and the TPtr8 iFramePtr to it |
|
376 // Then calls the SetPayload() method with the param aHCIPayload |
|
377 iFrame = HBufC8::NewL(aHCIPayload.Length() + KBcspHeaderBytes + KBcspCrcBytes); |
|
378 iFramePtr.Set(iFrame->Des()); |
|
379 |
|
380 SetPayload(aHCIPayload); |
|
381 } |
|
382 |
|
383 void CTxHctlBcspFrame::ConstructL(TInt aFrameSize) |
|
384 { |
|
385 LOG_FUNC |
|
386 |
|
387 // Instantiates iFrame and the TPtr8 iFramePtr to it |
|
388 // then calls the SetPayload() method. |
|
389 iFrame = HBufC8::NewL(KBcspHeaderBytes + KBcspCrcBytes + aFrameSize); |
|
390 iFramePtr.Set(iFrame->Des()); |
|
391 |
|
392 SetPayload(); |
|
393 } |
|
394 |
|
395 void CTxHctlBcspFrame::SetPayload(const TDesC8 &aPayload) |
|
396 { |
|
397 iFramePtr.SetMax(); |
|
398 TPtr8 payload(iFramePtr.MidTPtr(KBcspHeaderBytes)); |
|
399 |
|
400 payload = aPayload.Right(payload.MaxSize()); |
|
401 iPayloadPtr.Set(payload); |
|
402 |
|
403 iFramePtr.SetLength(KBcspHeaderBytes + aPayload.Size()); |
|
404 |
|
405 iIsValid = ETrue; |
|
406 } |
|
407 |
|
408 void CTxHctlBcspFrame::SetPayload() |
|
409 { |
|
410 LOG_FUNC |
|
411 iPayloadPtr.Set(KNullDesC8); |
|
412 |
|
413 iFramePtr.SetLength(KBcspHeaderBytes); |
|
414 |
|
415 iIsValid = ETrue; |
|
416 } |
|
417 |
|
418 CTxHctlBcspFrame::CTxHctlBcspFrame() |
|
419 : iFramePtr(NULL, 0, 0) |
|
420 { |
|
421 LOG_FUNC |
|
422 } |
|
423 |
|
424 CTxHctlBcspFrame::~CTxHctlBcspFrame() |
|
425 { |
|
426 LOG_FUNC |
|
427 delete iFrame; |
|
428 } |
|
429 |
|
430 void CTxHctlBcspFrame::BuildFrame() |
|
431 /** |
|
432 Build BCSP frame method |
|
433 |
|
434 Zero the frame Ptr |
|
435 Set the frame length to KMaxHeaderBytes - to address the BCSP header bytes |
|
436 |
|
437 Populate all 4 header bytes with the Flag byte,PayloadLength, ProtocolId and checksum |
|
438 |
|
439 Set the frame length to Payloadlength + KMaxBcspHeaderBytes |
|
440 |
|
441 Populate the BCSP frame payload |
|
442 |
|
443 Check if the CRC flag is set if it is then Calculate the CRC of the Whole Frame and append the crc |
|
444 |
|
445 */ |
|
446 { |
|
447 LOG_FUNC |
|
448 iFramePtr.SetLength(KBcspHeaderBytes); |
|
449 iFramePtr[KBcspHeaderFlagsByteIndex] = iFlagHeaderByte.FlagsField(); |
|
450 iFramePtr[KBcspHeaderByte2Index] = static_cast<TUint8>(ProtocolId() | ((PayloadLength() & 0xf) << 4)); |
|
451 iFramePtr[KBcspHeaderByte3Index] = static_cast<TUint8>((PayloadLength() & 0xff0) >> 4); |
|
452 iFramePtr[KBcspHeaderChecksumByteIndex] = CalcCheckSum(iFramePtr); |
|
453 |
|
454 iFramePtr.SetLength(PayloadLength() + KBcspHeaderBytes); |
|
455 |
|
456 if (PayloadLength() > 0) |
|
457 { |
|
458 iPayloadPtr.Set(iFramePtr.Ptr() + KBcspHeaderBytes, PayloadLength()); |
|
459 } |
|
460 |
|
461 if (CrcEnabled()) |
|
462 { |
|
463 TUint16 crcValue = CalcCRC(iFramePtr.Left(PayloadLength() + KBcspHeaderBytes)); |
|
464 iFramePtr.Append((crcValue & 0xff00) >> 8); //Append first byte of CRC |
|
465 iFramePtr.Append(crcValue & 0x00ff); //Append second Byte of CRC |
|
466 } |
|
467 } |
|
468 |
|
469 void CTxHctlBcspFrame::Reset() |
|
470 /** |
|
471 Reset the BCSP frame and set retries to 0 |
|
472 */ |
|
473 { |
|
474 LOG_FUNC |
|
475 CHCTLBcspFrame::Reset(); |
|
476 iRetries = 0; |
|
477 } |
|
478 |
|
479 void CTxHctlBcspFrame::SlipEncodeFrame(TPtr8 aSlipFrame) |
|
480 /** |
|
481 SlipEncoding method |
|
482 SLIP is outlined in RFC 1055. The principle is to surround each packet |
|
483 with a start and an end special byte. This allows the beginning and the end of a packet to be |
|
484 found and consequently the length of the packet to be known. |
|
485 The packet encoding and decoding scheme has two basic rules: |
|
486 Because the special byte can only appear in the stream as a delimiter, it has to be replaced inside |
|
487 the payload by an escape sequence, composed of two bytes: 0xc0 is mapped to 0xDB 0xDC. |
|
488 Consequently 0xDB is also a special byte, and each occurrence of this escape byte is replaced |
|
489 by an another sequence of two bytes: 0xDB 0xDD |
|
490 This method is very quick and simple for encoding a packet. The corresponding Decoding |
|
491 procedure is used for received packets. |
|
492 Moreover, as explained in the section regarding detecting errors, the SLIP layer provides a |
|
493 method of error detection. |
|
494 */ |
|
495 { |
|
496 LOG_FUNC |
|
497 __ASSERT_DEBUG(iFrame != NULL, PANIC(KBcspPanicCat, EBadFramePointer)); |
|
498 |
|
499 aSlipFrame.Zero(); |
|
500 aSlipFrame.SetMax(); |
|
501 |
|
502 TInt i=0; |
|
503 TInt j=0; |
|
504 |
|
505 aSlipFrame[j++] = KSlipWrapperByte; |
|
506 |
|
507 for (i=0;i<iFrame->Length();i++) |
|
508 { |
|
509 switch((*iFrame)[i]) |
|
510 { |
|
511 case KSlipWrapperByte: |
|
512 { |
|
513 aSlipFrame[j++] = KSlipByteDB; |
|
514 aSlipFrame[j++] = KSlipByteDC; |
|
515 break; |
|
516 } |
|
517 case 0xdb: |
|
518 { |
|
519 aSlipFrame[j++] = KSlipByteDB; |
|
520 aSlipFrame[j++] = KSlipByteDD; |
|
521 break; |
|
522 } |
|
523 |
|
524 default: |
|
525 { |
|
526 aSlipFrame[j++] = (*iFrame)[i]; |
|
527 break; |
|
528 } |
|
529 } |
|
530 } |
|
531 |
|
532 aSlipFrame[j++] = KSlipWrapperByte; |
|
533 aSlipFrame.SetLength(j); |
|
534 } |
|
535 |
|
536 |
|
537 |
|
538 /** |
|
539 Implementation of Class CRxHctlBcspFrame |
|
540 */ |
|
541 |
|
542 |
|
543 CRxHctlBcspFrame* CRxHctlBcspFrame::NewL() |
|
544 /** |
|
545 CRxHctlBcspFrame::NewL() method |
|
546 |
|
547 @return self |
|
548 */ |
|
549 { |
|
550 LOG_STATIC_FUNC |
|
551 return new(ELeave) CRxHctlBcspFrame; |
|
552 } |
|
553 |
|
554 TInt CRxHctlBcspFrame::SlipDecodeFrame(const TDesC8& aReceivedFrame) |
|
555 /** |
|
556 Slip decoding methopd for received frames |
|
557 */ |
|
558 { |
|
559 LOG_FUNC |
|
560 TInt rerr = KErrNone; |
|
561 |
|
562 // TPtrC8 packet = aReceivedFrame; |
|
563 TPtr8 packet(const_cast<TUint8*>(aReceivedFrame.Ptr()), |
|
564 aReceivedFrame.Size(), |
|
565 aReceivedFrame.Size()); |
|
566 |
|
567 if ((packet.Length() < KBcspHeaderBytes) || (packet[packet.Length()-1] != KSlipWrapperByte) || (packet[0] == KSlipWrapperByte)) |
|
568 { |
|
569 /** |
|
570 Fail slip decoding for one of or none of these reasons: |
|
571 1. first byte is another slip wrapper byte (One has been received already and discarded in terminating reads) |
|
572 should not receive 2 consecutive slip wrapper byte in any one slip packet |
|
573 2. The final packet byte is not a slip wrapper byte |
|
574 |
|
575 NB. A good slip Packet at this stage should have x-bytes appended with one slip wrapper byte. |
|
576 This is because the first slip wrapper byte was already picked up on the first terminated read. |
|
577 */ |
|
578 rerr = KErrSlipCorrupted; |
|
579 } |
|
580 else |
|
581 { |
|
582 packet.SetLength(packet.Length() - 1); // Remove the last 0xc0 byte. |
|
583 |
|
584 TInt i = 0; |
|
585 TInt offset = 0; |
|
586 TInt length = packet.Length(); |
|
587 |
|
588 while ( (i<length) && (rerr == KErrNone) ) |
|
589 { |
|
590 switch (packet[i]) |
|
591 { |
|
592 case 0xc0: // If this appears do nothing as it should be either the header or trailer byte checked above |
|
593 rerr = KErrSlipCorrupted; |
|
594 break; |
|
595 |
|
596 case 0xdb: |
|
597 i++; // Check the next byte immediately |
|
598 offset--; |
|
599 if ( i<length ) |
|
600 { |
|
601 switch (packet[i]) |
|
602 { |
|
603 case 0xdc: |
|
604 packet[i+offset] = 0xc0; |
|
605 break; |
|
606 |
|
607 case 0xdd: |
|
608 packet[i+offset] = 0xdb; |
|
609 break; |
|
610 |
|
611 default: |
|
612 rerr = KErrSlipCorrupted; |
|
613 }; |
|
614 } |
|
615 else |
|
616 { |
|
617 rerr = KErrSlipCorrupted; |
|
618 } |
|
619 break; |
|
620 |
|
621 default: |
|
622 if ( offset ) |
|
623 { |
|
624 packet[i+offset] = packet[i]; |
|
625 } |
|
626 break; |
|
627 } |
|
628 i++; |
|
629 } |
|
630 |
|
631 if(rerr == KErrNone) |
|
632 { |
|
633 packet.SetLength(length + offset); |
|
634 rerr = Set(packet); |
|
635 } |
|
636 } |
|
637 |
|
638 return rerr; |
|
639 } |
|
640 |
|
641 TInt CRxHctlBcspFrame::Set(const TDesC8& aFrame) |
|
642 /** |
|
643 Populate a BCSP frame object and vaildate its contents via the various BCSP error |
|
644 checking methods |
|
645 */ |
|
646 { |
|
647 LOG_FUNC |
|
648 TInt err = ValidateChecksum(aFrame); // Do Checksum check |
|
649 TInt errId = KErrNone; |
|
650 TUint16 payloadLen = 0; |
|
651 |
|
652 if (err == KErrNone) |
|
653 { |
|
654 ParseFlagByte(aFrame); // populate THctlBcspFlags members |
|
655 |
|
656 errId = ParsePayloadLenProtId(aFrame, payloadLen); |
|
657 if (errId) |
|
658 { |
|
659 return errId; // corrupted Id, no point in continuing |
|
660 } |
|
661 |
|
662 // Check header payload length field is the same as the actual HCIPayloadLength |
|
663 if (CrcEnabled()) |
|
664 { |
|
665 TInt actualPayloadLen = aFrame.Length() - KBcspCrcBytes - KBcspHeaderBytes; |
|
666 if(actualPayloadLen >= 0) // Check payload is sufficient length |
|
667 { |
|
668 iPayloadPtr.Set(aFrame.Ptr() + KBcspHeaderBytes, actualPayloadLen); |
|
669 |
|
670 if (PayloadLength() != payloadLen) // Check payload length |
|
671 { |
|
672 LOG(_L8("CRxHctlBcspFrame: KErrBcspCorruptedHCIPayload...")); |
|
673 err = KErrBcspCorruptedHCIPayload; |
|
674 } |
|
675 else if (CheckCRC(aFrame) != KErrNone) // Do CRC Check |
|
676 { |
|
677 LOG(_L8("CRxHctlBcspFrame: KErrBCSPCRCCheckFailed...")); |
|
678 err = KErrBcspCRCCheckFailed; |
|
679 } |
|
680 } |
|
681 else |
|
682 { |
|
683 LOG(_L8("CRxHctlBcspFrame: KErrBcspCorruptedHCIPayload...")); |
|
684 err = KErrBcspCorruptedHCIPayload; |
|
685 } |
|
686 } |
|
687 else |
|
688 { |
|
689 TInt actualPayloadLen = aFrame.Length() - KBcspHeaderBytes; |
|
690 // There is no need to check that the payload is of sufficient length since |
|
691 // the ValidateChecksum call would have failed and stopped us getting here. |
|
692 __ASSERT_DEBUG(actualPayloadLen >= 0, PANIC(KBcspPanicCat, EBadBcspFrame)); |
|
693 iPayloadPtr.Set(aFrame.Ptr() + KBcspHeaderBytes, actualPayloadLen); |
|
694 if (PayloadLength() != payloadLen) |
|
695 { |
|
696 LOG(_L8("HCTLBcsp: KErrBcspCorruptedHCIPayload...")); |
|
697 LOGHEXDESC(aFrame); |
|
698 err = KErrBcspCorruptedHCIPayload; |
|
699 } |
|
700 } |
|
701 } |
|
702 |
|
703 iIsValid = (err == KErrNone) ? ETrue : EFalse; |
|
704 |
|
705 return err; |
|
706 } |
|
707 |
|
708 |
|
709 CRxHctlBcspFrame::CRxHctlBcspFrame() |
|
710 : CHCTLBcspFrame() |
|
711 { |
|
712 } |
|
713 |
|
714 void CRxHctlBcspFrame::ParseFlagByte(const TDesC8& aHeader) |
|
715 { |
|
716 LOG_FUNC |
|
717 LOG1(_L8("Parse HeaderByte %02x"), aHeader[KBcspHeaderFlagsByteIndex]); |
|
718 |
|
719 iFlagHeaderByte.SetFlagsField(aHeader[KBcspHeaderFlagsByteIndex]); |
|
720 } |
|
721 |
|
722 TInt CRxHctlBcspFrame::ParsePayloadLenProtId(const TDesC8& aHeader, TUint16& aRetPayloadLen) |
|
723 /** |
|
724 Method to extract the Payload Length and Protocol Id from the 2nd and 3rd header bytes |
|
725 */ |
|
726 { |
|
727 LOG_FUNC |
|
728 TInt err = KErrNone; |
|
729 |
|
730 err = SetProtocolId((aHeader[KBcspHeaderByte2Index] & KBcspProtocolIdMask)); |
|
731 if (!err) |
|
732 { |
|
733 aRetPayloadLen = static_cast<TUint16>(((aHeader[KBcspHeaderByte2Index] & KBcspPayloadLen1stBitsMask) >> 4) | (aHeader[KBcspHeaderByte3Index] << 4)); |
|
734 } |
|
735 |
|
736 return err; |
|
737 } |
|
738 |
|
739 TInt CRxHctlBcspFrame::CheckCRC(const TDesC8 &aFrame) |
|
740 /** |
|
741 Method to check and validate the CRC |
|
742 */ |
|
743 { |
|
744 LOG_FUNC |
|
745 TPtrC8 frame(aFrame.Ptr(), aFrame.Size() - KBcspCrcBytes); |
|
746 |
|
747 TUint16 tempCRCvalue; |
|
748 TUint16 crcValue = CalcCRC(frame); // Calculates and sets iCRCValue |
|
749 |
|
750 //compare with hctl trailer CRC value |
|
751 TBuf8<2> crcval; |
|
752 crcval = aFrame.Right(KBcspCrcBytes); |
|
753 |
|
754 tempCRCvalue = static_cast<TUint16>((crcval[0] << 8) + crcval[1]); |
|
755 |
|
756 return ((crcValue == tempCRCvalue) ? KErrNone : KErrBcspCRCCheckFailed); |
|
757 } |