bluetooth/btstack/rfcomm/rfcommframe.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     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)