bluetooth/btstack/l2cap/L2CapPDU.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2004-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_prot.h>
       
    18 #include <bluetooth/hci/aclpacketconsts.h>
       
    19 
       
    20 #include "L2CapPDU.h"
       
    21 #include "l2capCommand.h"
       
    22 #include "l2signalmgr.h"
       
    23 #include "L2CapDataController.h"
       
    24 #include "L2CapSDU.h"
       
    25 #include "L2CapDebugControlInterface.h"
       
    26 
       
    27 #ifdef __FLOG_ACTIVE
       
    28 _LIT8(KLogComponent, LOG_COMPONENT_L2CAP_PDU);
       
    29 #endif
       
    30 
       
    31 TDataPlaneElementHandle::TDataPlaneElementHandle(MDataPlaneElement* aDataElement, TUint16 aElementID)
       
    32 	{
       
    33 	LOG_FUNC
       
    34 	SetUserLen(sizeof(SDataPlaneElementHandle));
       
    35 	SDataPlaneElementHandle* handlePtr = reinterpret_cast<SDataPlaneElementHandle*>(UserPtr());
       
    36 	handlePtr->iDataElement = aDataElement;
       
    37 	handlePtr->iElementID = aElementID;
       
    38 	}
       
    39 
       
    40 MDataPlaneElement& TDataPlaneElementHandle::DataPlaneElement() const
       
    41 	{
       
    42 	LOG_FUNC
       
    43 	SDataPlaneElementHandle* handlePtr = reinterpret_cast<SDataPlaneElementHandle*>(UserPtr());
       
    44 	return *(handlePtr->iDataElement);
       
    45 	}
       
    46 	
       
    47 TUint16 TDataPlaneElementHandle::ElementID() const
       
    48 	{
       
    49 	LOG_FUNC
       
    50 	SDataPlaneElementHandle* handlePtr = reinterpret_cast<SDataPlaneElementHandle*>(UserPtr());
       
    51 	return (handlePtr->iElementID);
       
    52 	}
       
    53 
       
    54 
       
    55 //
       
    56 // Base class for all PDU types.
       
    57 //
       
    58 // Disable warning WINS 4355: 'this' : used in base member initializer list
       
    59 // This will not cause any problems in this usage and is preferable to the use of a
       
    60 // non-owned pointer.
       
    61 #pragma warning (disable: 4355)
       
    62 HL2CapPDU::HL2CapPDU(RMBufChain& aPDUData, TInt aOptimalFragmentSize)
       
    63  : iIsFlushed(EFalse),
       
    64    iSendingError(EFalse),
       
    65    iQueuedForSend(EFalse),
       
    66    iAwaitingHciCompletion(EFalse), // first transmission never waits for a previous one to finish
       
    67    iElementHandle(this),
       
    68    iPduOwner(NULL),
       
    69    iOptimalFragmentSize(aOptimalFragmentSize),
       
    70    iTotalNumberOfFragments(KNumberOfFragmentsUnknown),
       
    71    iFragmentAcksReceived(0)
       
    72 	{
       
    73 	LOG_FUNC
       
    74 	iPDUData.Assign(aPDUData);
       
    75 	iPDUData.Align(Min(iPDUData.Length(), KMaxPDUHeaderLength));
       
    76 
       
    77 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::EBasePDU,
       
    78 	                             L2capDebugInfo::EAllocated));
       
    79 	}
       
    80 
       
    81 HL2CapPDU::HL2CapPDU(TInt aOptimalFragmentSize)
       
    82  : iIsFlushed(EFalse),
       
    83    iSendingError(EFalse),
       
    84    iQueuedForSend(EFalse),
       
    85    iAwaitingHciCompletion(EFalse), // first transmission never waits for a previous one to finish
       
    86    iElementHandle(this),
       
    87    iPduOwner(NULL),
       
    88    iOptimalFragmentSize(aOptimalFragmentSize),
       
    89    iTotalNumberOfFragments(KNumberOfFragmentsUnknown),
       
    90    iFragmentAcksReceived(0)
       
    91 	{
       
    92 	LOG_FUNC
       
    93 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::EBasePDU,
       
    94 	                             L2capDebugInfo::EAllocated));
       
    95 	}
       
    96 #pragma warning (default: 4355)
       
    97 
       
    98 
       
    99 HL2CapPDU::~HL2CapPDU()
       
   100 	{
       
   101 	LOG_FUNC
       
   102 	iPDUData.Free();
       
   103 
       
   104 	iLink.Deque();
       
   105 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::EBasePDU,
       
   106 	                             L2capDebugInfo::EDeleted));
       
   107 	}
       
   108 	
       
   109 	
       
   110 // Static Message Accessors.
       
   111 /*static*/ TBool HL2CapPDU::AddFragment(RMBufChain& aPDU, RMBufChain& aPDUFragment)
       
   112 	{
       
   113 	LOG_STATIC_FUNC
       
   114 	if(aPDUFragment.First()!= NULL)
       
   115 		{
       
   116 		aPDU.Append(aPDUFragment);
       
   117 		return ((aPDU.Length() - KPDUHeaderLength) >= PDUPayloadLength(aPDU));
       
   118 		}
       
   119 	else
       
   120 		{
       
   121 		return(EFalse);
       
   122 		}
       
   123 	}
       
   124 
       
   125 /*static*/ TUint16 HL2CapPDU::PDUPayloadLength(const RMBufChain& aPDU)
       
   126 	{
       
   127 	LOG_STATIC_FUNC
       
   128 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KPDUHeaderLength,
       
   129 		           Panic(EL2CapPDUInvalidLength));
       
   130 	return LittleEndian::Get16((aPDU.First())->Ptr()+KLengthByteOffset);
       
   131 	}
       
   132 
       
   133 /*static*/ TUint16 HL2CapPDU::PDUCID(const RMBufChain& aPDU)
       
   134 	{
       
   135 	LOG_STATIC_FUNC
       
   136 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KPDUHeaderLength,
       
   137 		           Panic(EL2CapPDUInvalidLength));
       
   138 	return LittleEndian::Get16((aPDU.First())->Ptr()+KCIDByteOffset);
       
   139 	}
       
   140 
       
   141 void HL2CapPDU::SetPDUPayloadLength(TUint16 aLength)
       
   142 	{
       
   143 	LOG_FUNC
       
   144 	__ASSERT_DEBUG(iPDUData.First() && (iPDUData.First())->Length() >= KPDUHeaderLength,
       
   145 		           Panic(EL2CapPDUInvalidLength));
       
   146 	LittleEndian::Put16((iPDUData.First())->Ptr()+KLengthByteOffset, aLength);
       
   147 	}
       
   148 
       
   149 void HL2CapPDU::SetPDUCID(TUint16 aCID)
       
   150 	{
       
   151 	LOG_FUNC
       
   152 	__ASSERT_DEBUG(iPDUData.First() && (iPDUData.First())->Length() >= KPDUHeaderLength,
       
   153 		           Panic(EL2CapPDUInvalidLength));
       
   154 	LittleEndian::Put16((iPDUData.First())->Ptr()+KCIDByteOffset, aCID);
       
   155 	}
       
   156 
       
   157 void HL2CapPDU::WritePDUPayloadLength()
       
   158 	{
       
   159 	LOG_FUNC
       
   160 	SetPDUPayloadLength(static_cast<TUint16>(iPDUData.Length() - KPDUHeaderLength));
       
   161 	}
       
   162 	
       
   163 /*
       
   164  * Function to return the PDU L2CAP overhead.
       
   165  */
       
   166 /*static*/ TInt HL2CapPDU::GetPDUOrFragmentOverhead(TBool aBasicMode)
       
   167 	{
       
   168 	LOG_STATIC_FUNC
       
   169 	if (aBasicMode)
       
   170 		{
       
   171 		// Basic mode does not segment into PDUs and therefore has no PDU overhead
       
   172 		return 0;
       
   173 		}
       
   174 	
       
   175 	// Non-basic mode overhead
       
   176 	return KPDUHeaderLength + KControlFieldLength + KFCSFieldLength;
       
   177 	}
       
   178 
       
   179 /*
       
   180  * Return the payload size of the optimal pdu based on the baseband packet
       
   181  * sizes, the negotiated MTU (aMTU) and the size of the buffers on the 
       
   182  * controller (aBufSize).
       
   183  * SDU length field is taken into account when it get segmented by CL2CapSDU::SegmentSDUIntoPDUs
       
   184  */
       
   185 /*static*/ TInt HL2CapPDU::GetPDUOrFragmentSize(TInt aMTU, TInt aMaxMps, TInt aBufSize, TBool aBasicMode)
       
   186 	{
       
   187 	LOG_STATIC_FUNC
       
   188 	// aBufSize == 0 means that getting the buffer size failed so assume the best
       
   189 	// case scenario for performance
       
   190 	TInt bufSize = aBufSize != 0 ? aBufSize : KBBPacketSize[KBaseBandPacketCount - 1];
       
   191 
       
   192 	// get the overhead size for every l2cap pdu	
       
   193 	TInt packetOverhead = GetPDUOrFragmentOverhead(aBasicMode);
       
   194 
       
   195 	// it's possible that the buffer size is so small that when including the packet overhead there is no
       
   196 	// room for a payload, this is of course no good.
       
   197 	__ASSERT_ALWAYS((bufSize - packetOverhead) > 0, Panic(EL2CAPACLBufferTooSmall));
       
   198 
       
   199 	// store the current baseband packet size as we go through the below for loop
       
   200 	TInt currentPacketSize;
       
   201 
       
   202 	// iterate backwards through the baseband packet sizes array
       
   203 	for (TInt index = KBaseBandPacketCount - 1; index >= 0; index--)
       
   204 		{
       
   205 		currentPacketSize = KBBPacketSize[index];
       
   206 
       
   207 		if (aMTU >= (index > 0 ? ((currentPacketSize + KBBPacketSize[index - 1]) / 2) : currentPacketSize))
       
   208 			{
       
   209 			if (bufSize >= currentPacketSize)
       
   210 				{
       
   211 				// if the current baseband packet size is less than the MTU size and the baseband
       
   212 				// packet will fit into the controllers buffer then use the baseband packet
       
   213 				return (aBasicMode ? (currentPacketSize - packetOverhead) : Min(aMaxMps, (currentPacketSize - packetOverhead)));
       
   214 				}
       
   215 			else if ((index > 0) && (bufSize >= ((currentPacketSize + KBBPacketSize[index - 1]) / 2)))
       
   216 				{
       
   217 				// if the current baseband packet is less than the MTU but the baseband packet
       
   218 				// won't fit into the controllers buffer see if the buffer size is closer to the
       
   219 				// current baseband packet than the next size down and if so use the buffer size
       
   220 				// of the controller
       
   221 				return (aBasicMode ? (bufSize - packetOverhead) : Min(aMaxMps, (bufSize - packetOverhead)));
       
   222 				}
       
   223 			}
       
   224 		}
       
   225 
       
   226 	// to get here means that the buffer size of the controller or the MTU is less than the minimum
       
   227 	// baseband packet size. A small ACL buffer reduces performance as there is a big overhead to data
       
   228 	// ratio, but we handle that situation anyway.
       
   229 	return (aBasicMode ? (bufSize - packetOverhead) : Min(aMaxMps, (bufSize - packetOverhead)));
       
   230 	}
       
   231 
       
   232 /*static*/ TInt HL2CapPDU::CheckDecode(const RMBufChain& aPDU)
       
   233 	{
       
   234 	LOG_STATIC_FUNC
       
   235 	TInt rerr = KErrNone;
       
   236 	if(aPDU.Length() != (PDUPayloadLength(aPDU) + KPDUHeaderLength))
       
   237 		{
       
   238 		rerr = KErrCorrupt;
       
   239 		}
       
   240 	return rerr;
       
   241 	} 
       
   242 
       
   243 void HL2CapPDU::AppendPayloadToBuffer(RMBufChain& /*aSDUData*/)
       
   244 	{
       
   245 	LOG_FUNC
       
   246 	Panic(EL2CAPInvalidCallToAppendPayloadToBuffer);
       
   247 	}
       
   248 
       
   249 void HL2CapPDU::DeliverOutgoingPDU(MOutgoingPDUHandler& aPDUHandler)
       
   250 	{
       
   251 	iAwaitingHciCompletion = ETrue;
       
   252 	DeliverOutgoingPDUDoubleDispatch(aPDUHandler);
       
   253 	}
       
   254 
       
   255 
       
   256 void HL2CapPDU::PDUSendPending(TUint16 aTotalNumberOfFragments)
       
   257 	{
       
   258 	LOG_FUNC
       
   259 	// The fragment sender has completed sending the PDU to the
       
   260 	// ACL.
       
   261 	__ASSERT_DEBUG(iTotalNumberOfFragments == KNumberOfFragmentsUnknown, Panic(EL2CAPPDUSendPendingCalledTwice));
       
   262 
       
   263 	iTotalNumberOfFragments = aTotalNumberOfFragments;
       
   264 	
       
   265 	// In some error conditions the expected number of outstanding fragments might
       
   266 	// have been reached before this method is called.
       
   267 	if(iFragmentAcksReceived == iTotalNumberOfFragments)
       
   268 		{
       
   269 		PDUSendComplete();
       
   270 		}
       
   271 	}
       
   272 
       
   273 void HL2CapPDU::PDUSendComplete()
       
   274 	{
       
   275 	LOG_FUNC
       
   276 	iAwaitingHciCompletion = EFalse;
       
   277 
       
   278 	if(!iIsFlushed && iPduOwner)
       
   279 		{
       
   280 		iFragmentAcksReceived = 0;
       
   281 		iTotalNumberOfFragments = KNumberOfFragmentsUnknown;
       
   282 
       
   283 		if(!iSendingError)
       
   284 			{
       
   285 			// Do frame-type specific stuff.
       
   286 			SendComplete();
       
   287 
       
   288 			iPduOwner->HandlePduSendComplete(*this);
       
   289 			}
       
   290 		else
       
   291 			{
       
   292 			iSendingError = EFalse; // in case the owner decides to resend us
       
   293 			iPduOwner->HandlePduSendError(*this);
       
   294 			}
       
   295 		}
       
   296 	else
       
   297 		{
       
   298 		// No references are held to this PDU.  Delete it.
       
   299 		delete this;
       
   300 		}
       
   301 	}
       
   302 	
       
   303 
       
   304 // MDataPlaneElement Interface
       
   305 void HL2CapPDU::DataElementSent(TUint16 /*aElementID*/)
       
   306 	{
       
   307 	LOG_FUNC
       
   308 	// Check if the PDU has been fully sent to the peer.
       
   309 	if(++iFragmentAcksReceived == iTotalNumberOfFragments)
       
   310 		{
       
   311 		PDUSendComplete();
       
   312 		}
       
   313 	}
       
   314 	
       
   315 void HL2CapPDU::DataElementFlushed(TUint16 aElementID)
       
   316 	{
       
   317 	LOG_FUNC
       
   318 	// Check if this PDU has been flushed.
       
   319 	if(!iIsFlushed)
       
   320 		{
       
   321 		iSendingError = ETrue;
       
   322 		}
       
   323 	DataElementSent(aElementID);
       
   324 	}
       
   325 	
       
   326 TUint16 HL2CapPDU::CalcCRC(const RMBufChain& aPDU)
       
   327  	{
       
   328  	LOG_STATIC_FUNC
       
   329   	TUint16 crcValue = 0;
       
   330   	TUint8 dataByte;
       
   331 	TInt i, bufLength;
       
   332 	TUint16 carryBit, bitCount;
       
   333 	
       
   334 	const RMBuf* bufPtr = aPDU.First();
       
   335 	TInt fcsLength = aPDU.Length() - KFCSFieldLength;
       
   336 	TInt byteCount = 0;
       
   337 	while(bufPtr)
       
   338 		{
       
   339 		// Check if this is the last buffer.  If so don't
       
   340 		// process the FCS bytes.
       
   341 		bufLength = bufPtr->Length();
       
   342 	 	for(i=0;i<bufLength;i++)
       
   343 	  		{
       
   344 	  		if(byteCount < fcsLength)
       
   345 	  			{
       
   346 		  		dataByte = bufPtr->Get(i);
       
   347 		  		byteCount++;
       
   348 				for(bitCount=0;bitCount<8;bitCount++)
       
   349 					{
       
   350 					carryBit = static_cast<TUint16>(crcValue & 0x8000 ? 1 : 0);
       
   351 					crcValue <<= 1;
       
   352 					if ((dataByte & 1) ^ carryBit)
       
   353 						{
       
   354 						crcValue ^= 0x8005;
       
   355 						}
       
   356 					dataByte >>= 1;
       
   357 					}
       
   358 				}
       
   359   			}
       
   360   		
       
   361   		bufPtr = bufPtr->Next();
       
   362   		}
       
   363 
       
   364 	carryBit = 0;
       
   365 	for(bitCount=0;bitCount<16;bitCount++)
       
   366 		{
       
   367 		carryBit = static_cast<TUint16>((carryBit >> 1) | (crcValue & 0x8000));
       
   368 		crcValue <<= 1;
       
   369 		}
       
   370   		
       
   371   	return carryBit;
       
   372   	}
       
   373 
       
   374 void HL2CapPDU::SendComplete()
       
   375 	{
       
   376 	LOG_FUNC
       
   377 	// Nothing to do for most PDUs.
       
   378 	}
       
   379 
       
   380 
       
   381 //
       
   382 // Class used to fragment and send any type of PDU.
       
   383 // An instance of this class is currently owned by the Mux
       
   384 //
       
   385 HFragmentedPDUSender::HFragmentedPDUSender(CL2CAPMux& aMuxer)
       
   386  : iPDU(NULL),
       
   387    iPDUBuffer(NULL),
       
   388    iMuxer(aMuxer),
       
   389    iCurrentWriteIndex(0),
       
   390    iCurrentFragmentID(0),
       
   391    iPDULength(0)
       
   392 	{
       
   393 	LOG_FUNC
       
   394 	}
       
   395 
       
   396 HFragmentedPDUSender::~HFragmentedPDUSender()
       
   397 	{
       
   398 	LOG_FUNC
       
   399 	delete iPDUBuffer;
       
   400 	__ASSERT_DEBUG(iPDU == NULL, Panic(EL2CAPFragmentSenderDeletedWhileSending));
       
   401 	}
       
   402 
       
   403 TInt HFragmentedPDUSender::FragmentPDU(HL2CapPDU& aPDU)
       
   404 	{
       
   405 	LOG_FUNC
       
   406 	TInt rerr = KErrNone;
       
   407 	__ASSERT_DEBUG(!iCurrentWriteIndex && !iCurrentFragmentID, Panic(EL2CAPRequestToFragmentWhileBufferContainsData));
       
   408 
       
   409 	RMBufChain& pduData = aPDU.PDUBuffer();
       
   410 	if(!iPDUBuffer || iPDUBuffer->Size() < pduData.Length())
       
   411 		{
       
   412 		// Increase the size of the buffer.
       
   413 		delete iPDUBuffer; 
       
   414 		iPDUBuffer = HBufC8::New(pduData.Length());
       
   415 		}
       
   416 
       
   417 	if(iPDUBuffer)
       
   418 		{
       
   419 		iPDU = &aPDU;
       
   420 		iPDULength = pduData.Length();
       
   421 		
       
   422 		// Copy the Buffer into the descriptor
       
   423   		TPtr8 ptr = iPDUBuffer->Des();
       
   424   		ptr.SetLength(iPDULength);
       
   425 		pduData.CopyOut(ptr);
       
   426 
       
   427 		// store the optimal fragment size
       
   428 		iPDUFragmentSize = aPDU.OptimalFragmentSize();
       
   429 		}
       
   430 	else
       
   431 		{
       
   432 		rerr = KErrNoMemory;
       
   433 		}
       
   434 	return rerr;
       
   435 	}
       
   436 
       
   437 HFragmentedPDUSender::TFragmentSenderStatus HFragmentedPDUSender::WriteNextFragment(CServProviderBase& aSender, TInt aACLMTU)
       
   438 	{
       
   439 	LOG_FUNC
       
   440 	// If optimal fragment size not set then this PDU should only have been segmented, not fragmented
       
   441 	__ASSERT_DEBUG((iPDULength <= aACLMTU) || (iPDUFragmentSize != 0), Panic(EL2CAPUnexpectedFragmentation));
       
   442 	if (iPDUFragmentSize == 0)
       
   443 		{
       
   444 		// For udeb builds we know that this PDU can fit into the ACL buffer so just set the fragment size
       
   445 		// to be the ACL buffer size to allow logic below to work. For urel builds this can also recover the
       
   446 		// situation if the debug assert fails above, just not using optimal performance.
       
   447 		iPDUFragmentSize = aACLMTU;
       
   448 		}
       
   449 
       
   450 	// Ensure that the optimal fragment size will fit into the ACL buffer.
       
   451 	__ASSERT_DEBUG(aACLMTU >= iPDUFragmentSize, Panic(EL2CAPOptimalFragmentSizeTooBigForACLBuffer));
       
   452 
       
   453 	TFragmentSenderStatus rStatus = EFragmentOK;
       
   454 
       
   455 	TUint8 flags = iCurrentWriteIndex ? KContinuingHLFragment : KFirstHLFragment;
       
   456 
       
   457 	TInt fragLength = Min(iPDULength - iCurrentWriteIndex, Min(iPDUFragmentSize, aACLMTU));
       
   458 	
       
   459 	// The 'Write' returns the number of fragments (NOT bytes) 
       
   460 	// that will be sent. This is typically either 0 or 1.
       
   461 	TUint fragmentsSent = aSender.Write(iPDUBuffer->Mid(iCurrentWriteIndex, fragLength), flags, &iPDU->ElementHandle()); 
       
   462 	if(!fragmentsSent)
       
   463 		{
       
   464 		rStatus = EFlowControlledOff;
       
   465 		}
       
   466 	else
       
   467 		{
       
   468 		iCurrentWriteIndex += fragLength;
       
   469 		iCurrentFragmentID++;
       
   470 		}
       
   471 	
       
   472 	// Check if the PDU has been fully sent.
       
   473 	if(iCurrentWriteIndex >= iPDULength)
       
   474 		{
       
   475 		rStatus = EFragmentationComplete;
       
   476 		
       
   477 		// Inform the PDU that it has been sent.
       
   478 		iPDU->PDUSendPending(iCurrentFragmentID);
       
   479 		
       
   480 		// Reset the internal state of this sender.
       
   481 		Reset();
       
   482 		}
       
   483 	return rStatus; 
       
   484 	}
       
   485 
       
   486 void HFragmentedPDUSender::Reset()
       
   487 	{
       
   488 	LOG_FUNC
       
   489 	iPDU = NULL;
       
   490 	iPDULength = iCurrentWriteIndex = 0;
       
   491 	iCurrentFragmentID = 0;
       
   492 	iPDUFragmentSize = 0;
       
   493 	}
       
   494 
       
   495 void HFragmentedPDUSender::CheckForFlushed()
       
   496 	{
       
   497 	LOG_FUNC
       
   498 	// Check if the PDU currently being sent(if there is one)
       
   499 	// needs to be flushed.
       
   500 	if(iPDU)
       
   501 		{
       
   502 		if(iPDU->IsPDUFlushed())
       
   503 			{
       
   504 			// Inform the PDU that it has been sent.
       
   505 			iPDU->PDUSendPending(iCurrentFragmentID);
       
   506 			
       
   507 			// Reset the internal state of this sender.
       
   508 			Reset();
       
   509 			}
       
   510 		}
       
   511 	}
       
   512 
       
   513 void HFragmentedPDUSender::PDUSenderFailed()
       
   514 	{
       
   515 	LOG_FUNC
       
   516 	if(iPDU)
       
   517 		{
       
   518 		// Inform the PDU that it has been sent.
       
   519 		iPDU->PDUSendPending(iCurrentFragmentID);
       
   520 		
       
   521 		// Reset the internal state of this sender.
       
   522 		Reset();
       
   523 		}
       
   524 	}
       
   525 
       
   526 
       
   527 
       
   528 //
       
   529 // Basic frame PDU class.
       
   530 //
       
   531 HBFramePDU::HBFramePDU(RMBufChain& aPDUData, TInt aOptimalFragmentSize)
       
   532  : HL2CapPDU(aPDUData, aOptimalFragmentSize)
       
   533 	{
       
   534 	LOG_FUNC
       
   535 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::EBFrame,
       
   536 	                             L2capDebugInfo::EAllocated));
       
   537 	}
       
   538 
       
   539 HBFramePDU::~HBFramePDU()
       
   540 	{
       
   541 	LOG_FUNC
       
   542 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::EBFrame,
       
   543 	                             L2capDebugInfo::EDeleted));
       
   544 	}
       
   545 
       
   546 HBFramePDU* HBFramePDU::New(RMBufChain& aPayloadData, TInt aOptimalFragmentSize)
       
   547 	{
       
   548 	LOG_STATIC_FUNC
       
   549 	HBFramePDU* self = NULL;
       
   550 	TRAPD(rerr, aPayloadData.PrependL(KPDUHeaderLength));
       
   551 	if(rerr == KErrNone)
       
   552 		{
       
   553 		self = new HBFramePDU(aPayloadData, aOptimalFragmentSize);
       
   554 		}
       
   555 	
       
   556 	if(self)
       
   557 		{	
       
   558 		self->WritePDUPayloadLength();
       
   559 		}
       
   560 	return self;
       
   561 	}
       
   562 
       
   563 void HBFramePDU::DeliverOutgoingPDUDoubleDispatch(MOutgoingPDUHandler& aPDUHandler)
       
   564 	{
       
   565 	LOG_FUNC
       
   566 	aPDUHandler.HandleOutgoingBFrame(this);
       
   567 	}
       
   568 
       
   569 void HBFramePDU::AppendPayloadToBuffer(RMBufChain& aSDUData)
       
   570 	{
       
   571 	LOG_FUNC
       
   572 	// Remove header and trailing bytes.
       
   573 	iPDUData.TrimStart(KPDUHeaderLength);
       
   574 	aSDUData.Append(iPDUData);
       
   575 	}
       
   576 
       
   577 /*static*/ void HBFramePDU::RemoveHeaderBytes(RMBufChain& aPDU)
       
   578 	{
       
   579 	LOG_STATIC_FUNC
       
   580 	// Remove header bytes.
       
   581 	aPDU.TrimStart(KPDUHeaderLength);
       
   582 	}
       
   583 
       
   584 void HBFramePDU::SendComplete()
       
   585 	{
       
   586 	LOG_FUNC
       
   587 	L2CAP_DEBUG_PDU(PDUTimer(L2capDebugInfo::EPDUSent, this, PDUCID()));
       
   588 	}
       
   589 
       
   590 
       
   591 //
       
   592 // Information frame PDU class.
       
   593 //
       
   594 HIFramePDU::HIFramePDU(RMBufChain& aPDUData)
       
   595  : HL2CapPDU(aPDUData, 0),
       
   596    iTransmissionCount(0),
       
   597    iAcked(EFalse)
       
   598 	{
       
   599 	LOG_FUNC
       
   600 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::EIFrame,
       
   601 	                             L2capDebugInfo::EAllocated));
       
   602 	}
       
   603 
       
   604 HIFramePDU::~HIFramePDU()
       
   605 	{
       
   606 	LOG_FUNC
       
   607 	LOG1(_L("Deleting TxSeq = %d"), TxSeqNumber());
       
   608 
       
   609 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::EIFrame,
       
   610 	                             L2capDebugInfo::EDeleted));
       
   611 	}
       
   612 
       
   613 
       
   614 HIFramePDU* HIFramePDU::New(RMBufChain& aPayloadData, TL2CapSAR aPduSAR)
       
   615 	{
       
   616 	LOG_STATIC_FUNC
       
   617 	TInt rerr = KErrNone;
       
   618 	HIFramePDU* self = NULL;
       
   619 
       
   620 	switch(aPduSAR)
       
   621 		{
       
   622 		case EStartOfL2CapSDU:
       
   623 			TRAP(rerr, aPayloadData.PrependL(KPDUHeaderLength + KControlFieldLength + KSDULengthFieldLength));
       
   624 			break;
       
   625 		case EUnsegmentedL2CapSDU:
       
   626 		case EEndOfL2CapSDU:
       
   627 		case EContinuationOfL2CapSDU:
       
   628 			TRAP(rerr, aPayloadData.PrependL(KPDUHeaderLength + KControlFieldLength));
       
   629 			break;
       
   630 			
       
   631 		default:
       
   632 			Panic(EL2CAPInvalidPDUSAR);
       
   633 			break;
       
   634 		};		
       
   635 
       
   636 	if(rerr == KErrNone)
       
   637 		{
       
   638 		TRAP(rerr, aPayloadData.AppendL(KFCSFieldLength));
       
   639 		}
       
   640 
       
   641 	if(rerr == KErrNone)
       
   642 		{
       
   643 		self = new HIFramePDU(aPayloadData);
       
   644 		if(self)
       
   645 			{
       
   646 			self->WritePDUPayloadLength();
       
   647 			self->SetIFrameControlDefault();
       
   648 			self->SetSAR(aPduSAR);
       
   649 			}
       
   650 		}
       
   651 
       
   652 	return self;
       
   653 	}
       
   654 
       
   655 void HIFramePDU::DeliverOutgoingPDUDoubleDispatch(MOutgoingPDUHandler& aPDUHandler)
       
   656 	{
       
   657 	LOG_FUNC
       
   658 	aPDUHandler.HandleOutgoingIFrame(this);
       
   659 	}	
       
   660 
       
   661 // Message Accessors.
       
   662 /*static*/ TBool HIFramePDU::IFrameIdentifier(const RMBufChain& aPDU)
       
   663 	{
       
   664 	LOG_STATIC_FUNC
       
   665 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
   666 		           Panic(EL2CapPDUInvalidLength));
       
   667 	TUint16 ctrl = LittleEndian::Get16((aPDU.First())->Ptr()+KControlFieldByteOffset);
       
   668 	return (!(ctrl & KCtrlFrameTypeMask));
       
   669 	}
       
   670 
       
   671 /*static*/ TUint8 HIFramePDU::TxSeqNumber(const RMBufChain& aPDU)
       
   672 	{
       
   673 	LOG_STATIC_FUNC
       
   674 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
   675 		           Panic(EL2CapPDUInvalidLength));
       
   676 	TUint16 ctrl = LittleEndian::Get16((aPDU.First())->Ptr()+KControlFieldByteOffset);
       
   677 	return static_cast<TUint8>((ctrl & KCtrlTxSeqMask) >> KCtrlTxSeqShift);
       
   678 	}
       
   679 
       
   680 /*static*/ TBool HIFramePDU::FinalBit(const RMBufChain& aPDU)
       
   681 	{
       
   682 	LOG_STATIC_FUNC
       
   683 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
   684 	           Panic(EL2CapPDUInvalidLength));
       
   685 	TUint16 ctrl = LittleEndian::Get16((aPDU.First())->Ptr()+KControlFieldByteOffset);
       
   686 	return (ctrl & KCtrlFinalBitMask);
       
   687 	}
       
   688 
       
   689 void HIFramePDU::SetFinalBit(TBool aFinalBit)
       
   690 	{
       
   691 	LOG_FUNC
       
   692 	SetRetransmitDisable(aFinalBit);
       
   693 	}
       
   694 
       
   695 void HIFramePDU::SetTxSeqNumber(TUint8 aTxSeqNum)
       
   696 	{
       
   697 	LOG_FUNC
       
   698 	__ASSERT_DEBUG(iPDUData.First() && (iPDUData.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
   699 		           Panic(EL2CapPDUInvalidLength));
       
   700 	TUint16 ctrl = LittleEndian::Get16((iPDUData.First())->Ptr()+KControlFieldByteOffset);
       
   701 	ctrl &= ~KCtrlTxSeqMask;
       
   702 	ctrl |= (aTxSeqNum << KCtrlTxSeqShift);
       
   703 	LittleEndian::Put16((iPDUData.First())->Ptr()+KControlFieldByteOffset, ctrl);
       
   704 	}
       
   705 
       
   706 /*static*/ TBool HIFramePDU::RetransmitDisable(const RMBufChain& aPDU)
       
   707 	{
       
   708 	LOG_STATIC_FUNC
       
   709 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
   710 		           Panic(EL2CapPDUInvalidLength));
       
   711 	return (LittleEndian::Get16((aPDU.First())->Ptr()+KControlFieldByteOffset) & KCtrlReTxDisableMask);
       
   712 	}
       
   713 	
       
   714 void HIFramePDU::SetRetransmitDisable(TBool aReTxDisable)
       
   715 	{
       
   716 	LOG_FUNC
       
   717 	__ASSERT_DEBUG(iPDUData.First() && (iPDUData.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
   718 		           Panic(EL2CapPDUInvalidLength));
       
   719 	TUint16 ctrl = LittleEndian::Get16((iPDUData.First())->Ptr()+KControlFieldByteOffset);
       
   720 	ctrl &= ~KCtrlReTxDisableMask;
       
   721 	ctrl |= (aReTxDisable << KCtrlReTxDisableShift);
       
   722 	LittleEndian::Put16((iPDUData.First())->Ptr()+KControlFieldByteOffset, ctrl);	
       
   723 	}
       
   724 
       
   725 /*static*/ TUint8 HIFramePDU::ReqSeqNumber(const RMBufChain& aPDU)
       
   726 	{
       
   727 	LOG_STATIC_FUNC
       
   728 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
   729 		           Panic(EL2CapPDUInvalidLength));
       
   730 	TUint16 ctrl = LittleEndian::Get16((aPDU.First())->Ptr()+KControlFieldByteOffset);
       
   731 	return static_cast<TUint8>((ctrl & KCtrlReqSeqMask) >> KCtrlReqSeqShift);
       
   732 	}
       
   733 
       
   734 void HIFramePDU::SetReqSeqNumber(TUint8 aReqSeqNum)
       
   735 	{
       
   736 	LOG_STATIC_FUNC
       
   737 	__ASSERT_DEBUG(iPDUData.First() && (iPDUData.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
   738 		           Panic(EL2CapPDUInvalidLength));
       
   739 	TUint16 ctrl = LittleEndian::Get16((iPDUData.First())->Ptr()+KControlFieldByteOffset);
       
   740 	ctrl &= ~KCtrlReqSeqMask;
       
   741 	ctrl |= (aReqSeqNum << KCtrlReqSeqShift);
       
   742 	LittleEndian::Put16((iPDUData.First())->Ptr()+KControlFieldByteOffset, ctrl);
       
   743 	}
       
   744 
       
   745 /*static*/ TBool HIFramePDU::IsStartOfSDU(const RMBufChain& aPDU)
       
   746 	{
       
   747 	LOG_STATIC_FUNC
       
   748 	return (SAR(aPDU) == EUnsegmentedL2CapSDU || SAR(aPDU) == EStartOfL2CapSDU);
       
   749 	}
       
   750 
       
   751 	
       
   752 /*static*/ TL2CapSAR HIFramePDU::SAR(const RMBufChain& aPDU)
       
   753 	{
       
   754 	LOG_STATIC_FUNC
       
   755 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
   756 		           Panic(EL2CapPDUInvalidLength));
       
   757 	TUint16 ctrl = LittleEndian::Get16((aPDU.First())->Ptr()+KControlFieldByteOffset);
       
   758 	return TL2CapSAR((ctrl & KCtrlSARMask) >> KCtrlSARShift);
       
   759 	}
       
   760 	
       
   761 void HIFramePDU::SetSAR(TL2CapSAR aSARValue)
       
   762 	{
       
   763 	LOG_FUNC
       
   764 	__ASSERT_DEBUG(iPDUData.First() && (iPDUData.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
   765 		           Panic(EL2CapPDUInvalidLength));
       
   766 	TUint16 ctrl = LittleEndian::Get16((iPDUData.First())->Ptr()+KControlFieldByteOffset);
       
   767 	ctrl &= ~KCtrlSARMask;
       
   768 	TUint8 sar = static_cast<TUint8>(aSARValue);
       
   769 	ctrl |= (sar << KCtrlSARShift);
       
   770 	LittleEndian::Put16((iPDUData.First())->Ptr()+KControlFieldByteOffset, ctrl);	
       
   771 	}
       
   772 	
       
   773 /*static*/ TUint16 HIFramePDU::SDUSize(const RMBufChain& aPDU)
       
   774 	{
       
   775 	LOG_STATIC_FUNC
       
   776 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KSDULengthFieldLength + KSDULengthFieldByteOffset,
       
   777 		           Panic(EL2CapPDUInvalidLength));
       
   778 	
       
   779 	return LittleEndian::Get16((aPDU.First())->Ptr()+KSDULengthFieldByteOffset);	
       
   780 	}
       
   781 	
       
   782 void HIFramePDU::SetSDUSize(TUint16 aSDUSize)
       
   783 	{
       
   784 	LOG_FUNC
       
   785 	LittleEndian::Put16((iPDUData.First())->Ptr()+KSDULengthFieldByteOffset, aSDUSize);
       
   786 	}
       
   787 	
       
   788 void HIFramePDU::CalculateAndSetFCS()
       
   789 	{
       
   790 	LOG_FUNC
       
   791 
       
   792 	TUint16 fcs = HL2CapPDU::CalcCRC();
       
   793 	
       
   794 	RMBuf* buf = iPDUData.Last();	
       
   795 	if(buf->Length() < KFCSFieldLength)
       
   796 		{
       
   797 		// This can only mean that the last buffer contains one byte.
       
   798 		// Get a pointer to the penultimate buffer.
       
   799 		buf = iPDUData.First();
       
   800 		for(TInt i=1;i<(iPDUData.NumBufs() - 1);i++)
       
   801 			{
       
   802 			buf = buf->Next();
       
   803 			}
       
   804 		buf->Put(static_cast<TUint8>(fcs & 0x00ff), buf->Length() - 1);
       
   805 		fcs = static_cast<TUint16>(fcs >> 8);
       
   806 		buf = buf->Next();
       
   807 		buf->Put(static_cast<TUint8>(fcs & 0x00ff), 0);
       
   808 		}
       
   809 	else
       
   810 		{
       
   811 		LittleEndian::Put16(buf->Ptr()+buf->Length()-KFCSFieldLength, fcs); 
       
   812 		}
       
   813 	}
       
   814 	
       
   815 /*static*/ TBool HIFramePDU::CheckFCS(const RMBufChain& aPDU)
       
   816 	{
       
   817 	LOG_STATIC_FUNC
       
   818 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KPDUHeaderLength + KFCSFieldLength,
       
   819 		           Panic(EL2CapPDUInvalidLength));
       
   820 
       
   821 	TUint16 msgFCS;
       
   822 	RMBuf* buf = aPDU.Last();
       
   823 	if(buf->Length() < KFCSFieldLength)
       
   824 		{
       
   825 		// This can only mean that the last buffer contains one byte.
       
   826 		msgFCS = static_cast<TUint16>((buf->Get(0)) << 8);
       
   827 		
       
   828 		// Get a pointer to the penultimate buffer.
       
   829 		const RMBuf* cBuf = aPDU.First();
       
   830 		for(TInt i=1;i<(aPDU.NumBufs() - 1);i++)
       
   831 			{
       
   832 			cBuf = cBuf->Next();
       
   833 			}
       
   834 		msgFCS |= cBuf->Get(cBuf->Length() - 1);
       
   835 		}
       
   836 	else
       
   837 		{
       
   838 		msgFCS = LittleEndian::Get16(buf->Ptr()+buf->Length()-KFCSFieldLength); 
       
   839 		}
       
   840 		
       
   841 	return (msgFCS == HL2CapPDU::CalcCRC(aPDU));
       
   842 	}
       
   843 
       
   844 TBool HIFramePDU::CheckFCS()
       
   845 	{
       
   846 	LOG_FUNC
       
   847 	return CheckFCS(iPDUData);
       
   848 	}
       
   849 	
       
   850 void HIFramePDU::SetIFrameControlDefault()
       
   851 	{
       
   852 	LOG_FUNC
       
   853 	LittleEndian::Put16((iPDUData.First())->Ptr()+KControlFieldByteOffset, KIFrameControlDefault);
       
   854 	}
       
   855 
       
   856 
       
   857 void HIFramePDU::AppendPayloadToBuffer(RMBufChain& aSDUData)
       
   858 	{
       
   859 	LOG_FUNC
       
   860 	// Remove header and trailing bytes.
       
   861 	if(SAR() == EStartOfL2CapSDU)
       
   862 		{
       
   863 		iPDUData.TrimStart(KPDUHeaderLength + KControlFieldLength + KSDULengthFieldLength);
       
   864 		}
       
   865 	else
       
   866 		{
       
   867 		iPDUData.TrimStart(KPDUHeaderLength + KControlFieldLength);
       
   868 		}
       
   869 	iPDUData.TrimEnd(iPDUData.Length()-KFCSFieldLength);
       
   870 	aSDUData.Append(iPDUData);
       
   871 	}
       
   872 
       
   873 /*static*/ void HIFramePDU::RemoveHeaderAndFCSBytes(RMBufChain& aPDU)
       
   874 	{
       
   875 	// Remove header and trailing bytes.
       
   876 	if(SAR(aPDU) == EStartOfL2CapSDU)
       
   877 		{
       
   878 		aPDU.TrimStart(KPDUHeaderLength + KControlFieldLength + KSDULengthFieldLength);
       
   879 		}
       
   880 	else
       
   881 		{
       
   882 		aPDU.TrimStart(KPDUHeaderLength + KControlFieldLength);
       
   883 		}
       
   884 	aPDU.TrimEnd(aPDU.Length()-KFCSFieldLength);
       
   885 	}
       
   886 
       
   887 /*static*/ TInt HIFramePDU::CheckPayloadDecode(const RMBufChain& aPDU)
       
   888 	{
       
   889 	LOG_STATIC_FUNC
       
   890 	TInt rerr = KErrNone;
       
   891 	
       
   892 	if(PDUCID(aPDU) < KL2CapDynamicCIDStart)
       
   893 		{
       
   894 		rerr = KErrCorrupt;
       
   895 		}
       
   896 	else if(!CheckFCS(aPDU))
       
   897 		{
       
   898 		rerr = KErrCorrupt;
       
   899 		}
       
   900 	return rerr;
       
   901 	}
       
   902 
       
   903 /*static*/ TInt HIFramePDU::CheckLengthWithinLimits(const RMBufChain& aPDU, TUint16 aMps)
       
   904 	{
       
   905 	LOG_STATIC_FUNC
       
   906 	// Check that the PDU size is >= than minimal and that the information payload size is <= MPS. 
       
   907 
       
   908 	TInt err = KErrNone;
       
   909 	TBool hasSduLength = (SAR(aPDU) == EStartOfL2CapSDU);
       
   910 
       
   911 	TInt infoPayloadSize = PDUPayloadLength(aPDU) - KControlFieldLength - KFCSFieldLength;
       
   912 	if (hasSduLength)
       
   913 		{
       
   914 		infoPayloadSize -= KSDULengthFieldLength;
       
   915 		}
       
   916 
       
   917 	if (infoPayloadSize > aMps)
       
   918 		{
       
   919 		err = KErrL2CAPIncomingIFrameTooBig;
       
   920 		}
       
   921 	else
       
   922 		{
       
   923 		if (aPDU.Length() < (KPDUHeaderLength + KControlFieldLength + KFCSFieldLength))
       
   924 			{
       
   925 			err = KErrL2CAPIncomingIFrameTooSmall;
       
   926 			}
       
   927 		}
       
   928 
       
   929 	return err;
       
   930 	}
       
   931 
       
   932 /*static*/ TInt HIFramePDU::CheckStartSduLength(const RMBufChain& aPDU, TUint16 aMtu)
       
   933 	{
       
   934 	LOG_STATIC_FUNC
       
   935 	TInt err = KErrNone;
       
   936 
       
   937 	if (aPDU.Length() < (KPDUHeaderLength + KControlFieldLength + KSDULengthFieldLength + KFCSFieldLength))
       
   938 		{
       
   939 		err = KErrL2CAPIncomingIFrameTooSmall;
       
   940 		}
       
   941 	else if (SDUSize(aPDU) > aMtu)
       
   942 		{
       
   943 		err = KErrL2CAPIncomingSduTooBig;
       
   944 		}
       
   945 	return err;
       
   946 	}
       
   947 
       
   948 void HIFramePDU::SendComplete()
       
   949 	{
       
   950 	LOG_FUNC
       
   951 	iTransmissionCount++;
       
   952 		
       
   953 #ifdef _DEBUG	
       
   954 	if(SAR() == EEndOfL2CapSDU || SAR() == EUnsegmentedL2CapSDU)
       
   955 		{
       
   956 		L2CAP_DEBUG_PDU(PDUTimer(L2capDebugInfo::EPDUSent, this, PDUCID()));
       
   957 		}
       
   958 #endif
       
   959 	}
       
   960 
       
   961 
       
   962 //
       
   963 // Supervisory frame PDU class.
       
   964 //
       
   965 HSFramePDU* HSFramePDU::New(TSupervisoryFunction aFunction)
       
   966 	{
       
   967 	LOG_STATIC_FUNC
       
   968 	TInt rerr = KErrNone;
       
   969 	HSFramePDU* self = NULL;
       
   970 	 
       
   971 	RMBufChain frameBuffer;	
       
   972 	TRAP(rerr, frameBuffer.AllocL(KSFrameLength));
       
   973 
       
   974 	if(rerr == KErrNone)
       
   975 		{
       
   976 		self = new HSFramePDU(frameBuffer);
       
   977 		if(self)
       
   978 			{
       
   979 			self->WritePDUPayloadLength();
       
   980 			self->SetSFrameControlDefault();
       
   981 			self->SetSupervisoryFunction(aFunction);
       
   982 			}
       
   983 		else
       
   984 			{
       
   985 			frameBuffer.Free();
       
   986 			}
       
   987 		}
       
   988 	return self;
       
   989 	}
       
   990 
       
   991 HSFramePDU* HSFramePDU::NewL(TSupervisoryFunction aFunction)
       
   992 	{
       
   993 	LOG_STATIC_FUNC
       
   994 	HSFramePDU* self = New(aFunction);
       
   995 	if (self == NULL)
       
   996 		{
       
   997 		LEAVEL(KErrNoMemory);
       
   998 		}
       
   999 	return self;
       
  1000 	}
       
  1001 
       
  1002 HSFramePDU::HSFramePDU(RMBufChain& aPDUData)
       
  1003  : HL2CapPDU(aPDUData, 0)
       
  1004 	{
       
  1005 	LOG_FUNC
       
  1006 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::ESFrame,
       
  1007 	                             L2capDebugInfo::EAllocated));
       
  1008 	}
       
  1009 
       
  1010 HSFramePDU::~HSFramePDU()	
       
  1011 	{
       
  1012 	LOG_FUNC
       
  1013 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::ESFrame,
       
  1014 	                             L2capDebugInfo::EDeleted));
       
  1015 	}
       
  1016 
       
  1017 void HSFramePDU::DeliverOutgoingPDUDoubleDispatch(MOutgoingPDUHandler& aPDUHandler)
       
  1018 	{
       
  1019 	LOG_FUNC
       
  1020 	aPDUHandler.HandleOutgoingSFrame(this);
       
  1021 	}	
       
  1022 
       
  1023 /*static*/ TInt HSFramePDU::CheckLengthField(const RMBufChain& aPDU)
       
  1024 	{
       
  1025 	LOG_STATIC_FUNC
       
  1026 	TInt err = KErrNone;
       
  1027 
       
  1028 	// The length field doesn't include the L2CAP Basic header.
       
  1029 	if (PDUPayloadLength(aPDU) != KControlFieldLength + KFCSFieldLength)
       
  1030 		{
       
  1031 		err = KErrL2CAPInvalidIncomingSFrameSize;
       
  1032 		}
       
  1033 
       
  1034 	return err;
       
  1035 	}
       
  1036 
       
  1037 /*static*/ TInt HSFramePDU::CheckPayloadDecode(RMBufChain& aPDU)
       
  1038 	{
       
  1039 	LOG_STATIC_FUNC
       
  1040 	TInt rerr = KErrNone;
       
  1041 
       
  1042 	if(!CheckFCS(aPDU))
       
  1043 		{
       
  1044 		rerr = KErrCorrupt;
       
  1045 		}
       
  1046 
       
  1047 	return rerr;
       
  1048 	}
       
  1049 
       
  1050 /*static*/ TSupervisoryFunction HSFramePDU::SupervisoryFunction(const RMBufChain& aPDU)
       
  1051 	{
       
  1052 	LOG_STATIC_FUNC
       
  1053 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
  1054 		           Panic(EL2CapPDUInvalidLength));
       
  1055 
       
  1056 	TUint16 ctrl = LittleEndian::Get16((aPDU.First())->Ptr()+KControlFieldByteOffset);
       
  1057 	return TSupervisoryFunction((ctrl & KCtrlSupervisoryMask) >> 2);
       
  1058 	}
       
  1059 	
       
  1060 /*static*/ TUint8 HSFramePDU::ReqSeqNumber(const RMBufChain& aPDU)
       
  1061 	{
       
  1062 	LOG_STATIC_FUNC
       
  1063 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
  1064 		           Panic(EL2CapPDUInvalidLength));
       
  1065 
       
  1066 	TUint16 ctrl = LittleEndian::Get16((aPDU.First())->Ptr()+KControlFieldByteOffset);
       
  1067 	return static_cast<TUint8>((ctrl & KCtrlReqSeqMask) >> 8);
       
  1068 	}
       
  1069 
       
  1070 void HSFramePDU::SetSupervisoryFunction(TSupervisoryFunction aSupervisoryFunction)
       
  1071 	{
       
  1072 	LOG_FUNC
       
  1073 	TUint16 ctrl = LittleEndian::Get16((iPDUData.First())->Ptr()+KControlFieldByteOffset);
       
  1074 	ctrl &= ~KCtrlSupervisoryMask;
       
  1075 	ctrl |= (aSupervisoryFunction << 2);
       
  1076 	LittleEndian::Put16((iPDUData.First())->Ptr()+KControlFieldByteOffset, ctrl);
       
  1077 	}
       
  1078 	
       
  1079 /*static*/ TBool HSFramePDU::RetransmitDisable(const RMBufChain& aPDU)
       
  1080 	{
       
  1081 	LOG_STATIC_FUNC
       
  1082 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
  1083 		           Panic(EL2CapPDUInvalidLength));
       
  1084 
       
  1085 	return (LittleEndian::Get16((aPDU.First())->Ptr()+KControlFieldByteOffset) & KCtrlReTxDisableMask);
       
  1086 	}
       
  1087 
       
  1088 /*static*/ TBool HSFramePDU::FinalBit(const RMBufChain& aPDU)
       
  1089 	{
       
  1090 	LOG_STATIC_FUNC
       
  1091 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
  1092 		           Panic(EL2CapPDUInvalidLength));
       
  1093 
       
  1094 	return (LittleEndian::Get16((aPDU.First())->Ptr()+KControlFieldByteOffset) & KCtrlFinalBitMask);
       
  1095 	}
       
  1096 
       
  1097 /*static*/ TBool HSFramePDU::PollBit(const RMBufChain& aPDU)
       
  1098 	{
       
  1099 	LOG_STATIC_FUNC
       
  1100 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KControlFieldLength + KControlFieldByteOffset,
       
  1101 		           Panic(EL2CapPDUInvalidLength));
       
  1102 
       
  1103 	return (LittleEndian::Get16((aPDU.First())->Ptr()+KControlFieldByteOffset) & KCtrlPollBitMask);
       
  1104 	}
       
  1105 
       
  1106 void HSFramePDU::SetFinalBit(TBool aFinalBit)
       
  1107 	{
       
  1108 	LOG_FUNC
       
  1109 	TUint16 ctrl = LittleEndian::Get16((iPDUData.First())->Ptr()+KControlFieldByteOffset);
       
  1110 	ctrl &= ~KCtrlFinalBitMask;
       
  1111 	ctrl |= (aFinalBit << 7);
       
  1112 	LittleEndian::Put16((iPDUData.First())->Ptr()+KControlFieldByteOffset, ctrl);	
       
  1113 	}
       
  1114 
       
  1115 void HSFramePDU::SetPollBit(TBool aPollBit)
       
  1116 	{
       
  1117 	LOG_FUNC
       
  1118 	TUint16 ctrl = LittleEndian::Get16((iPDUData.First())->Ptr()+KControlFieldByteOffset);
       
  1119 	ctrl &= ~KCtrlPollBitMask;
       
  1120 	ctrl |= (aPollBit << 4);
       
  1121 	LittleEndian::Put16((iPDUData.First())->Ptr()+KControlFieldByteOffset, ctrl);	
       
  1122 	}
       
  1123 
       
  1124 void HSFramePDU::SetRetransmitDisable(TBool aReTxDisable)
       
  1125 	{
       
  1126 	LOG_FUNC
       
  1127 	TUint16 ctrl = LittleEndian::Get16((iPDUData.First())->Ptr()+KControlFieldByteOffset);
       
  1128 	ctrl &= ~KCtrlReTxDisableMask;
       
  1129 	ctrl |= (aReTxDisable << 7);
       
  1130 	LittleEndian::Put16((iPDUData.First())->Ptr()+KControlFieldByteOffset, ctrl);	
       
  1131 	}
       
  1132 
       
  1133 void HSFramePDU::SetReqSeqNumber(TUint8 aReqSeqNum)
       
  1134 	{
       
  1135 	LOG_FUNC
       
  1136 	TUint16 ctrl = LittleEndian::Get16((iPDUData.First())->Ptr()+KControlFieldByteOffset);
       
  1137 	ctrl &= ~KCtrlReqSeqMask;
       
  1138 	ctrl |= (aReqSeqNum << 8);
       
  1139 	LittleEndian::Put16((iPDUData.First())->Ptr()+KControlFieldByteOffset, ctrl);
       
  1140 	}
       
  1141 
       
  1142 void HSFramePDU::CalculateAndSetFCS()
       
  1143 	{
       
  1144 	LOG_FUNC
       
  1145 
       
  1146 	TUint16 fcs = HL2CapPDU::CalcCRC();
       
  1147 
       
  1148 	RMBuf* lastBuf = iPDUData.Last();
       
  1149 	if(lastBuf->Length() < KFCSFieldLength)
       
  1150 		{
       
  1151 		// This can only be 8 bytes long.  Align the buffer.
       
  1152 		iPDUData.Align(iPDUData.Length());
       
  1153 		lastBuf = iPDUData.Last();
       
  1154 		}
       
  1155 	LittleEndian::Put16(lastBuf->Ptr()+lastBuf->Length()-KFCSFieldLength, fcs);
       
  1156 	}
       
  1157 	
       
  1158 /*static*/ TBool HSFramePDU::CheckFCS(RMBufChain& aPDU)
       
  1159 	{
       
  1160 	LOG_STATIC_FUNC
       
  1161 	__ASSERT_DEBUG(aPDU.First() && (aPDU.First())->Length() >= KPDUHeaderLength + KFCSFieldLength,
       
  1162 		           Panic(EL2CapPDUInvalidLength));
       
  1163 
       
  1164 	TUint16 msgFCS;
       
  1165 	RMBuf* buf = aPDU.Last();
       
  1166 	if(buf->Length() < KFCSFieldLength)
       
  1167 		{
       
  1168 		// This can only be 8 bytes long.  Align the buffer.
       
  1169 		aPDU.Align(aPDU.Length());
       
  1170 		buf = aPDU.Last();
       
  1171 		}
       
  1172 
       
  1173 	msgFCS = LittleEndian::Get16(buf->Ptr()+buf->Length()-KFCSFieldLength); 
       
  1174 		
       
  1175 	return (msgFCS == HL2CapPDU::CalcCRC(aPDU));
       
  1176 	}
       
  1177 
       
  1178 TBool HSFramePDU::CheckFCS()
       
  1179 	{
       
  1180 	LOG_FUNC
       
  1181 	return CheckFCS(iPDUData);
       
  1182 	}
       
  1183 
       
  1184 void HSFramePDU::SetSFrameControlDefault()
       
  1185 	{
       
  1186 	LOG_FUNC
       
  1187 	LittleEndian::Put16((iPDUData.First())->Ptr()+KControlFieldByteOffset, KSFrameControlDefault);
       
  1188 	}
       
  1189 
       
  1190 
       
  1191 //
       
  1192 // Group frame PDU class.
       
  1193 //
       
  1194 HGFramePDU::HGFramePDU(RMBufChain& aPDUData)
       
  1195  : HL2CapPDU(aPDUData, 0)
       
  1196 	{
       
  1197 	LOG_FUNC
       
  1198 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::EGFrame,
       
  1199 	                             L2capDebugInfo::EAllocated));
       
  1200 	}
       
  1201 
       
  1202 HGFramePDU::~HGFramePDU()	
       
  1203 	{
       
  1204 	LOG_FUNC
       
  1205 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::EGFrame,
       
  1206 	                             L2capDebugInfo::EDeleted));
       
  1207 	}
       
  1208 
       
  1209 void HGFramePDU::DeliverOutgoingPDUDoubleDispatch(MOutgoingPDUHandler& aPDUHandler)
       
  1210 	{
       
  1211 	LOG_FUNC
       
  1212 	aPDUHandler.HandleOutgoingGFrame(this);
       
  1213 	}	
       
  1214 
       
  1215 void HGFramePDU::AppendPayloadToBuffer(RMBufChain& aSDUData)
       
  1216 	{
       
  1217 	LOG_FUNC
       
  1218 	// Remove header and trailing bytes.
       
  1219 	iPDUData.TrimStart(KPDUHeaderLength + KGFramePSMLength);
       
  1220 	aSDUData.Append(iPDUData);
       
  1221 	}
       
  1222 
       
  1223 
       
  1224 //
       
  1225 // Control frame PDU class.
       
  1226 //
       
  1227 /*static*/ HCFramePDU* HCFramePDU::New(TInt aOptimalFragmentSize)
       
  1228 	{
       
  1229 	LOG_STATIC_FUNC
       
  1230 	RMBufChain buf;
       
  1231 	HCFramePDU* cFrame = NULL;
       
  1232 	
       
  1233 	TRAPD(err, buf.AllocL(KCFrameHeaderLength));
       
  1234 	if(err == KErrNone)
       
  1235 		{
       
  1236 		cFrame = new HCFramePDU(buf, aOptimalFragmentSize);
       
  1237 		if(cFrame)
       
  1238 			{
       
  1239 			cFrame->SetPDUCID(KL2CapSignallingCID);
       
  1240 			cFrame->WritePDUPayloadLength();
       
  1241 			}
       
  1242 		else
       
  1243 			{
       
  1244 			buf.Free();
       
  1245 			}
       
  1246 		}
       
  1247 	return cFrame;
       
  1248 	}
       
  1249 
       
  1250 HCFramePDU::HCFramePDU(RMBufChain& aPDUData, TInt aOptimalFragmentSize)
       
  1251  : HL2CapPDU(aPDUData, aOptimalFragmentSize),
       
  1252    iCommands(_FOFF(HL2CapCommand, iLink)),
       
  1253    iCommandIter(iCommands)   
       
  1254 	{
       
  1255 	LOG_STATIC_FUNC
       
  1256 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::ECFrame,
       
  1257 	                             L2capDebugInfo::EAllocated));
       
  1258 	}
       
  1259 
       
  1260 HCFramePDU::~HCFramePDU()
       
  1261 	{
       
  1262 	LOG_FUNC
       
  1263 	__ASSERT_DEBUG(iCommands.IsEmpty(), Panic(EL2CAPDeleteCFrameWhileContainingCommands));
       
  1264 
       
  1265 	while(!iCommands.IsEmpty())
       
  1266 		{
       
  1267 		HL2CapCommand *cmd = iCommands.First();
       
  1268 		cmd->iLink.Deque();
       
  1269 		delete cmd;
       
  1270 		}
       
  1271 	
       
  1272 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::ECFrame,
       
  1273 	                             L2capDebugInfo::EDeleted));
       
  1274 	}
       
  1275 
       
  1276 void HCFramePDU::DeliverOutgoingPDUDoubleDispatch(MOutgoingPDUHandler& aPDUHandler)
       
  1277 	{
       
  1278 	LOG_FUNC
       
  1279 	aPDUHandler.HandleOutgoingCFrame(this);
       
  1280 	}
       
  1281 
       
  1282 TInt HCFramePDU::CheckDecode()
       
  1283 	{
       
  1284 	LOG_FUNC
       
  1285 	TInt rerr = KErrNone;
       
  1286 	if(iPDUData.Length() != (PDUPayloadLength() + KPDUHeaderLength))
       
  1287 		{
       
  1288 		rerr = KErrCorrupt;
       
  1289 		}
       
  1290 	else
       
  1291 		{
       
  1292 		rerr = CheckPayloadDecode();
       
  1293 		}
       
  1294 	return rerr;
       
  1295 	}
       
  1296 
       
  1297 TInt HCFramePDU::CheckPayloadDecode()
       
  1298 	{
       
  1299 	LOG_FUNC
       
  1300 	return CreateCommands();
       
  1301 	}
       
  1302    
       
  1303 
       
  1304 // Takes this original PDU and extracts out a list of the contained Command Frames
       
  1305 // Upon completion the original PDU will be freed, but this class will hold a list 
       
  1306 // CFrames.
       
  1307 TInt HCFramePDU::CreateCommands()
       
  1308 	{
       
  1309 	LOG_FUNC
       
  1310 	// Trim off the standard header.
       
  1311 	iPDUData.TrimStart(KCFrameHeaderLength);
       
  1312 	
       
  1313 	HL2CapCommand* cmd = NULL;
       
  1314 	
       
  1315 	// If a command is decoded it will be removed from the 
       
  1316 	// start of the buffer.
       
  1317 	TInt err = KErrNone;
       
  1318 	while(err == KErrNone)
       
  1319 		{
       
  1320 		err = HL2CapCommand::DecodeCommand(iPDUData, cmd);
       
  1321 		LOG1(_L("HCFramePDU::CreateCommands, DecodeCommand returned %d"), err);
       
  1322 
       
  1323 		if(err == KErrNone && cmd)
       
  1324 			{
       
  1325 			iCommands.AddLast(*cmd);
       
  1326 			}
       
  1327 		}
       
  1328 
       
  1329 	// A C-Frame must contain at least one command.
       
  1330 	if(iCommands.IsEmpty())
       
  1331 		{
       
  1332 		err = KErrCorrupt;
       
  1333 		}
       
  1334 	return (err == KErrCompletion ? KErrNone : err);
       
  1335 	}
       
  1336 
       
  1337 
       
  1338 HL2CapCommand* HCFramePDU::FirstCommand()
       
  1339 	{
       
  1340 	LOG_FUNC
       
  1341 	iCommandIter.SetToFirst();
       
  1342 	return iCommandIter++;
       
  1343 	}
       
  1344 
       
  1345 HL2CapCommand* HCFramePDU::NextCommand()
       
  1346 	{
       
  1347 	LOG_FUNC
       
  1348 	return iCommandIter++;
       
  1349 	}
       
  1350 	
       
  1351 	
       
  1352 TInt HCFramePDU::AddCommand(HL2CapCommand& aCommand, CL2CAPMux& aMuxer)
       
  1353 	{
       
  1354 	LOG_FUNC
       
  1355 	TInt rerr = KErrNone;
       
  1356 	// Check if there is room in the PDU.
       
  1357 	if((aCommand.CommandLength() + PDUPayloadLength()) <= aMuxer.SigMTU())
       
  1358 		{
       
  1359 		// Add this command onto end of PDU buff
       
  1360 		RMBufChain buf;
       
  1361 		rerr = aCommand.GetCommand(aMuxer, buf);
       
  1362 		if(rerr == KErrNone)
       
  1363 			{
       
  1364 			iPDUData.Append(buf);
       
  1365 
       
  1366 			WritePDUPayloadLength();
       
  1367 			}
       
  1368 		}
       
  1369 	else
       
  1370 		{
       
  1371 		rerr = KErrCompletion;
       
  1372 		}
       
  1373 	return rerr;
       
  1374 	}