bluetooth/btstack/rfcomm/rfcommmuxer.cpp
changeset 0 29b1cd4cb562
child 17 32ba20339036
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 // Rfcomm muxer
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <bluetooth/logger.h>
       
    19 
       
    20 #include <bt_sock.h>
       
    21 
       
    22 #include "rfcommmuxer.h"
       
    23 #include "rfcomm.h"
       
    24 #include "rfcommutil.h"
       
    25 #include "rfcommframe.h"
       
    26 #include "rfcommtypes.h"
       
    27 #include "rfcommfcs.h"
       
    28 #include "rfcommsap.h"
       
    29 
       
    30 #include "rfcommflow.h"
       
    31 #include "rfcommmuxchannel.h"
       
    32 #include "AsyncErrorKicker.h"
       
    33 
       
    34 #ifdef __FLOG_ACTIVE
       
    35 _LIT8(KLogComponent, LOG_COMPONENT_RFCOMM);
       
    36 #endif
       
    37 
       
    38 // Disable int to char warnings
       
    39 #ifdef __WINS__
       
    40 #pragma warning( disable : 4244 )
       
    41 #endif
       
    42 
       
    43 #ifdef __FLOG_ACTIVE
       
    44 _LIT(KCommandText, "command");
       
    45 _LIT(KResponseText, "response");
       
    46 #endif //__FLOG_ACTIVE
       
    47 
       
    48 const TUint8 KBitsForNumberInTInt = 32 - 1; // -1 is because we don't count the sign bit
       
    49 
       
    50 CRfcommMuxer* CRfcommMuxer::NewL(CRfcommProtocol& aProt, CProtocolBase& aL2CAP,
       
    51 								CMuxChannelStateFactory& aFactory)
       
    52 	/**
       
    53 	Factory function for CRfcommMuxer - called when local device initiates the connection.
       
    54 
       
    55 	Note the CProtocolBase passed in so that the muxer can create its own L2CAP SAP
       
    56 	**/
       
    57 	{
       
    58 	CRfcommMuxer* mux= new (ELeave) CRfcommMuxer(aProt,KInitiationDirectionOutgoing);
       
    59 	CleanupStack::PushL(mux);
       
    60 	mux->ConstructL(aFactory, aL2CAP);
       
    61 	CleanupStack::Pop();
       
    62 	return mux;
       
    63 	}
       
    64 
       
    65 CRfcommMuxer* CRfcommMuxer::NewL(CRfcommProtocol& aProt, CServProviderBase* aSAP,
       
    66 								CMuxChannelStateFactory& aFactory)
       
    67 	/**
       
    68 	Factory function for CRfcommMuxer - called when remote device initiates the connection.
       
    69 
       
    70 	Note the CServProviderBase passed in, which becomes the L2CAP SAP used by this muxer.
       
    71 
       
    72 	@param aSAP		 This is a connected L2CAP sap
       
    73 	@param aFactory  The Mux channel state factory
       
    74 	@return          A new Muxer in the right state
       
    75 	**/
       
    76 	{
       
    77 	CRfcommMuxer* mux= new (ELeave) CRfcommMuxer(aProt,KInitiationDirectionIncoming);
       
    78 	CleanupStack::PushL(mux);
       
    79 	mux->ConstructL(aFactory, aSAP);
       
    80 	CleanupStack::Pop();
       
    81 	return mux;
       
    82 	}
       
    83 
       
    84 
       
    85 CRfcommMuxer::CRfcommMuxer(CRfcommProtocol& aProt, TInitiationDirection aDirection)
       
    86 	: iSAPs(_FOFF(CRfcommSAP, iLink)),
       
    87 	  iOutboundQ(_FOFF(CRfcommFrame, iLink)),
       
    88 	  iResponseQ(_FOFF(CRfcommFrame, iLink)),
       
    89 	  iOutboundQLength(0),
       
    90 	  iProtocol(aProt),
       
    91 	  iDirection(aDirection),
       
    92 	  iMuxIdleTimeout(KRfcommMuxIdleTimeoutOpening),	  
       
    93 	  iCanSend(ETrue),
       
    94 	  iBlockedSAPs(_FOFF(CRfcommSAP, iLink)),
       
    95 	  iDataFramesSent(0),
       
    96 	  iL2CAPSendBlocked(EFalse),
       
    97 	  iTriedCBFC(EFalse),
       
    98 	  iCurrentCredit(0),
       
    99 	  iInitialTxCredit(0),
       
   100 	  iFlowStrategy(0)
       
   101 	{
       
   102 	TCallBack cb(IdleTimerExpired, this);
       
   103 	iIdleTimerEntry.Set(cb);
       
   104 	}
       
   105 
       
   106 void CRfcommMuxer::ConstructL(CMuxChannelStateFactory& aFactory, CProtocolBase& aL2CAP)
       
   107 	{ 
       
   108 	// Create a SAP for this to use
       
   109 	iBoundSAP=aL2CAP.NewSAPL(KSockSeqPacket);
       
   110 	iMuxChannel = new (ELeave) CRfcommMuxChannel(aFactory, *this, *iBoundSAP, CMuxChannelStateFactory::EClosed);
       
   111 
       
   112 	//	We now have a bound L2Cap SAP.
       
   113 	//  Use it to setup L2Cap config for RFComm.
       
   114 	TL2CapConfigPkg configPkg;
       
   115 	iProtocol.SetL2CapConfig(configPkg);
       
   116 	User::LeaveIfError(iBoundSAP->SetOption(KSolBtL2CAP, KL2CAPUpdateChannelConfig, configPkg));
       
   117 
       
   118 	CommonConstructL();
       
   119 	}
       
   120 
       
   121 void CRfcommMuxer::ConstructL(CMuxChannelStateFactory& aFactory, CServProviderBase* aSAP)
       
   122 	{ 
       
   123 	// SAP has been provided for this to use, so start it
       
   124 	__ASSERT_DEBUG(aSAP!=NULL, Panic(ERfcommNullSAPForMuxer));
       
   125 	iBoundSAP=aSAP;
       
   126 	iBoundSAP->Start();
       
   127 	TBTSockAddr btAddr;
       
   128 	aSAP->RemName(btAddr);
       
   129 	iRemoteAddr=btAddr.BTAddr();
       
   130 	iMuxChannel = new (ELeave) CRfcommMuxChannel(aFactory, *this, *iBoundSAP, CMuxChannelStateFactory::ELinkUp);
       
   131 	CommonConstructL();
       
   132 	}
       
   133 
       
   134 void CRfcommMuxer::CommonConstructL()
       
   135 	{
       
   136 	iBoundSAP->SetNotify(this);
       
   137 	TCallBack cb(TryToSendCallbackStatic,this);
       
   138 	iSendCallback=new (ELeave) CAsyncCallBack(cb, ECAsyncImmediatePriority);
       
   139 	iNextPacket=HBufC8::NewL(KRfcommDefaultMTU);  // This will do for now
       
   140 #ifdef NO_CBFC
       
   141 	iFlowStrategy = TRfcommFlowStrategyNonCreditBased::NewL(*this);
       
   142 #else
       
   143 	if(iProtocol.CBFCDisallowed())
       
   144 		{
       
   145 		SetFlowType(CRfcommFlowStrategyFactory::EFlowNonCreditBased);
       
   146 		iTriedCBFC = ETrue;
       
   147 		}
       
   148 	else
       
   149 		{
       
   150 		SetFlowType(CRfcommFlowStrategyFactory::EFlowInitial);
       
   151 		}
       
   152 #endif
       
   153 	}
       
   154 
       
   155 CRfcommMuxer::~CRfcommMuxer()
       
   156 	{
       
   157 	LOG(_L("CRfcommMuxer::~CRfcommMuxer"));
       
   158 
       
   159 	DequeIdleTimer();
       
   160 	DeleteQueuedFrames();
       
   161 	
       
   162 	// remove the references to this muxer in any SAPs it is/was linked to
       
   163 	TDblQueIter<CRfcommSAP> iter(iSAPs);
       
   164 	CRfcommSAP* sap;
       
   165 	while(iter)
       
   166 		{
       
   167 		sap=iter++;
       
   168 		if (sap)
       
   169 			{
       
   170 			sap->iMux = NULL;
       
   171 			sap->iLink.Deque();
       
   172 			}
       
   173 		}
       
   174 
       
   175 	
       
   176 	
       
   177 	delete iSendCallback;
       
   178 	delete iBoundSAP;
       
   179 	delete iNextPacket;
       
   180 	delete iMuxChannel;
       
   181 	}
       
   182 
       
   183 /***************************************************************************/
       
   184 /*
       
   185   Commands from the protocol.
       
   186   
       
   187 */
       
   188   
       
   189 
       
   190 void CRfcommMuxer::Bind(TBTDevAddr& aAddr)
       
   191 	/**
       
   192 	   Bind this mux to the given remote address
       
   193 	   
       
   194 	   Calling this function implies that this end is to be the
       
   195 	   initiator (direction bit = 1).  The bound sap will be used to
       
   196 	   create an L2CAP link to the remote end over which the RFCOMM
       
   197 	   frames will flow.  The muxchannel will then run this channel.
       
   198 	**/
       
   199 	{
       
   200 	iRemoteAddr=aAddr;
       
   201 	iMuxChannel->SetAddress(aAddr);
       
   202 	}
       
   203 
       
   204 void CRfcommMuxer::AddSAP(CRfcommSAP& aSAP)
       
   205 	/**
       
   206 	   Adds a sap to the Q for this mux.
       
   207 	**/
       
   208 	{
       
   209 	DequeIdleTimer();
       
   210 	iSAPs.AddFirst(aSAP);
       
   211 	if(iMuxChannel->IsOpen())
       
   212 		aSAP.MuxUp();
       
   213 	else
       
   214 		iMuxChannel->Open();  // Eventually calls back
       
   215 	}
       
   216 
       
   217 void CRfcommMuxer::DetachSAP(CRfcommSAP& aSAP)
       
   218 	/**
       
   219 	   Detach this sap.
       
   220 
       
   221 	   If it's the last one, shut down.  We clean out the outbound and
       
   222 	   response queues as we no longer want these frames since the sap
       
   223 	   has gone.
       
   224 	**/
       
   225 	{
       
   226 	aSAP.iLink.Deque();
       
   227 	aSAP.iMux=0;
       
   228 	
       
   229 	ClearOutboundQueue(aSAP);
       
   230 	ClearResponseQueue(aSAP);
       
   231 	CheckForIdle(ETrue);
       
   232 	}
       
   233 
       
   234 void CRfcommMuxer::GetInboundServerChannelsInUse(TFixedArray<TBool, KMaxRfcommServerChannel>& aChannelInUse)
       
   235 	/**
       
   236 	   Identify inbound server channels in use for connected SAPs.
       
   237 	   
       
   238 	   aChannelInUse is an array indexed by (server channel - 1) and on return 
       
   239 	   aChannelInUse will be updated with any inbound server channels that
       
   240 	   are currently in use by connected SAPs.
       
   241 	**/
       
   242 	{
       
   243 	TDblQueIter<CRfcommSAP> iter(iSAPs);
       
   244 	CRfcommSAP* sap;
       
   245 
       
   246 	// Only interested in cloned SAPs as this identifies if the SAP is for 
       
   247 	// an inbound connection
       
   248 	while(iter)
       
   249 		{
       
   250 		sap=iter++;		
       
   251 		if (sap->IsCloned())
       
   252 			{
       
   253 			aChannelInUse[sap->ServerChannel() - 1] = ETrue;
       
   254 			}
       
   255 		}
       
   256 
       
   257 	iter=iBlockedSAPs;
       
   258 	while(iter)
       
   259 		{
       
   260 		sap=iter++;
       
   261 		if (sap->IsCloned())
       
   262 			{
       
   263 			aChannelInUse[sap->ServerChannel() - 1] = ETrue;
       
   264 			}
       
   265 		}	
       
   266 	}
       
   267 
       
   268 /****************************************************************************/
       
   269 /*
       
   270   Notifications from the MSocketNotify interface
       
   271 	
       
   272 */
       
   273 
       
   274 void CRfcommMuxer::NewData(TUint aCount)
       
   275 	/**
       
   276 	   Called when new data is available.
       
   277 	   This is called each time a new packet of data arrives from L2CAP.
       
   278 	   We get to the data by calling GetData on the SAP.
       
   279 
       
   280 	   Frames never span a L2CAP packet, and are one per packet.
       
   281 
       
   282 	   This assumes a packet interface from L2CAP
       
   283 
       
   284 	   @param aCount  Number of new packets waiting
       
   285 	**/
       
   286 	{
       
   287  	if (aCount == KNewDataEndofData)
       
   288  		{
       
   289 		LOG(_L("RFCOMM: L2CAP signalled EndOfData"));
       
   290  		Disconnect();
       
   291  		}
       
   292 	else
       
   293 		{
       
   294 		LOG1(_L("RFCOMM: New data, count %d"), aCount);
       
   295 		//BLOG: KBlogNewData
       
   296 		iPacketsWaiting+=aCount;
       
   297 		while(CanProcessNewData() && iPacketsWaiting)
       
   298 			{
       
   299 			// Get a packet into the buffer
       
   300 			TPtr8 data=iNextPacket->Des();
       
   301 			data.SetMax();
       
   302 			iBoundSAP->GetData(data, 0);
       
   303 			// process the new data
       
   304 			ProcessFrame();
       
   305 			iPacketsWaiting--;
       
   306 			}
       
   307 		}
       
   308 	}
       
   309 
       
   310 
       
   311 void CRfcommMuxer::CanSend()
       
   312 	/**
       
   313 	   Notification that we can now send data to the lower layer.
       
   314 	**/
       
   315 	{
       
   316 	L2CAPBlocked(EFalse);
       
   317 	TryToSend();
       
   318 	}
       
   319 
       
   320 //CBFC
       
   321 CRfcommFlowStrategyFactory::TFlowStrategies CRfcommMuxer::FlowType()
       
   322 	{
       
   323 	return iFlowStrategy->FlowType();
       
   324 	}
       
   325 
       
   326 #ifdef NO_CBFC
       
   327 TBool CRfcommMuxer::FlowType(CRfcommFlowStrategyFactory::TFlowStrategies /*aFlow*/)
       
   328 	{
       
   329 	return EFalse;
       
   330 	}
       
   331 #else
       
   332 TBool CRfcommMuxer::SetFlowType(CRfcommFlowStrategyFactory::TFlowStrategies aFlow)
       
   333 	{
       
   334 	if(iTriedCBFC)
       
   335 		{
       
   336 		LOG(_L("RFCOMM: Requesting new flow strategy again: DISALLOWED"));
       
   337 		return EFalse;
       
   338 		}
       
   339 
       
   340 	switch(aFlow)
       
   341 		{
       
   342 	case CRfcommFlowStrategyFactory::EFlowCreditBased:
       
   343 		LOG(_L("RFCOMM: Requesting CBFC at SAP level"));
       
   344 		iTriedCBFC = ETrue;				// stop the test being done again
       
   345 		iFlowStrategy = &(iProtocol.FlowStrategyFactory()->GetFlowStrategy(aFlow));
       
   346 		break;
       
   347 	case CRfcommFlowStrategyFactory::EFlowNonCreditBased:
       
   348 		LOG(_L("RFCOMM: Not requesting CBFC at SAP level"));
       
   349 		iTriedCBFC = ETrue;				// stop the test being done again
       
   350 		iFlowStrategy = &(iProtocol.FlowStrategyFactory()->GetFlowStrategy(aFlow));
       
   351 		break;
       
   352 	default:
       
   353 		iFlowStrategy = &(iProtocol.FlowStrategyFactory()->GetFlowStrategy(CRfcommFlowStrategyFactory::EFlowInitial));
       
   354 		break;
       
   355 		}
       
   356 	return ETrue;
       
   357 	}
       
   358 #endif
       
   359 
       
   360 void CRfcommMuxer::DisallowCBFC()
       
   361 	{
       
   362 	iCBFCDisallowed = ETrue;
       
   363 	}
       
   364 
       
   365 void CRfcommMuxer::AllowCBFC()
       
   366 	{
       
   367 	iCBFCDisallowed = EFalse;
       
   368 	}
       
   369 
       
   370 TRfcommFlowStrategy* CRfcommMuxer::FlowStrategy()
       
   371 	{
       
   372 	return iFlowStrategy;
       
   373 	}
       
   374 
       
   375 
       
   376 
       
   377 void CRfcommMuxer::ConnectComplete(const TDesC8& /*aConnectData*/)
       
   378 	/**
       
   379 	   Version with connection data.
       
   380 
       
   381 	   Ignore the data (since L2CAP should never provide this!)
       
   382 	**/
       
   383 	{
       
   384 	ConnectComplete();
       
   385 	}
       
   386 
       
   387 void CRfcommMuxer::ConnectComplete(CServProviderBase& /*aSSP*/)
       
   388 	/**
       
   389 	   Incoming connection completed on listen socket.
       
   390 	**/
       
   391 	{
       
   392 	Panic(ERfcommIncomingNotSupported);
       
   393 	}
       
   394 
       
   395 void CRfcommMuxer::ConnectComplete(CServProviderBase& /*aSSP*/,const TDesC8& /*aConnectData*/)
       
   396 	{
       
   397 	Panic(ERfcommIncomingNotSupported);
       
   398 	}
       
   399 
       
   400 void CRfcommMuxer::CanClose(TDelete /*aDelete*/)
       
   401 	/**
       
   402 	   We must have asked the socket to shutdown, which means we're dying.
       
   403 	**/
       
   404 	{
       
   405 	LOG1(_L("RFCOMM: CanClose from L2CAP for mux %08x"), this);
       
   406 	iMuxChannel->CanClose();
       
   407 	}
       
   408 
       
   409 void CRfcommMuxer::CanClose(const TDesC8& /*aDisconnectData*/,TDelete /*aDelete*/)
       
   410 	{
       
   411 	Panic(ERfcommDisconnectDataNotSupported);
       
   412 	}
       
   413 
       
   414 void CRfcommMuxer::Error(TInt aError,TUint aOperationMask)
       
   415 	/**
       
   416 	   Something's gone wrong.
       
   417 
       
   418 	   We get told whether it's just this operation or all that are
       
   419 	   affected, but we'll just assume that all of them are bust for
       
   420 	   now.
       
   421 	**/
       
   422 	{
       
   423 	LOG1(_L("RFCOMM: Error on L2CAP sap %d"), aError);
       
   424 	if(aOperationMask & MSocketNotify::EErrorIoctl)
       
   425 		{
       
   426 		// This was an ioctl problem, so pass up to the saps
       
   427 		PropagateIoctlCompletion(aError, iIoctlLevel, iIoctlName, NULL);
       
   428 		iIoctlName=0;
       
   429 		iIoctlLevel=0;
       
   430 		}
       
   431 
       
   432 	// Pass this on to the Mux channel as well
       
   433 	iMuxChannel->Error(aError, aOperationMask);
       
   434 	}
       
   435 
       
   436 void CRfcommMuxer::MuxChannelError(TBool aFatal, TInt aError)
       
   437 	/**
       
   438 	   Something's gone wrong on the mux channel
       
   439 
       
   440 	   If this is a fatal error it means we need a new muxchannel,
       
   441 	   else we can live with it.  Either way we need to error all the
       
   442 	   existing saps.
       
   443 	**/
       
   444 	{
       
   445 	LOG1(_L("RFCOMM: Error on Mux %d"), aError)
       
   446     
       
   447 	TDblQueIter<CRfcommSAP> iter(iSAPs);
       
   448 	CRfcommSAP* sap;
       
   449 
       
   450 	// Erroring the saps will remove them from us when we signal a 
       
   451 	// general error
       
   452 	while(iter)
       
   453 		{
       
   454 		sap=iter++;
       
   455 		sap->Error(aError, CRfcommSAP::EErrorGeneral);
       
   456 		}
       
   457 	iter=iBlockedSAPs;
       
   458 	while(iter)
       
   459 		{
       
   460 		sap=iter++;
       
   461 		sap->Error(aError, CRfcommSAP::EErrorGeneral);
       
   462 		}
       
   463 
       
   464 	if(aFatal)
       
   465 		{
       
   466 		// The channel is now useless, and so is the mux
       
   467 		// Set the address to 0 to stop any more saps attaching
       
   468 		DeleteQueuedFrames();
       
   469 		iRemoteAddr=TInt64(0);
       
   470 		return;
       
   471 		}
       
   472 	CheckForIdle(ETrue);
       
   473 	}
       
   474 
       
   475 const TBTDevAddr& CRfcommMuxer::RemoteBTAddr() const
       
   476 	{
       
   477 	return iRemoteAddr;
       
   478 	}
       
   479 
       
   480 void CRfcommMuxer::MuxChannelDown()
       
   481 	/**
       
   482 	   The mux channel has gone down.
       
   483 	   Pass this on to the saps	
       
   484 	**/
       
   485 	{
       
   486 	CloseSAPs();
       
   487 	DeleteQueuedFrames(); // since we can't send or receive any more
       
   488 	CheckForIdle(ETrue);
       
   489 	}
       
   490 
       
   491 void CRfcommMuxer::CloseSAPs()
       
   492 	{
       
   493 	TDblQueIter<CRfcommSAP> iter(iSAPs);
       
   494 	CRfcommSAP* sap;
       
   495 
       
   496 	while(iter)
       
   497 		{
       
   498 		sap=iter++;
       
   499 		sap->LinkDown();
       
   500 		}
       
   501 	iter=iBlockedSAPs;
       
   502 	while(iter)
       
   503 		{
       
   504 		sap=iter++;
       
   505 		sap->LinkDown();
       
   506 		}
       
   507 	}
       
   508 
       
   509 void CRfcommMuxer::MuxChannelUp()
       
   510 	/**
       
   511 	   The mux channel has come up.
       
   512 
       
   513 	   We need to allocate the buffer for incoming packets.  Note this
       
   514 	   may not be the same as the RFCOMM MTU since we can't guarantee
       
   515 	   that the other end won't send us omore in an L2CAP packet.
       
   516 	**/
       
   517 	{
       
   518 
       
   519 	TPckgBuf<TInt> buf;
       
   520 	// Find out what the max data size is.
       
   521 	iBoundSAP->GetOption(KSolBtL2CAP, KL2CAPInboundMTU, buf);
       
   522 	TInt incoming = buf();
       
   523 
       
   524 	TRAPD(err, iNextPacket=iNextPacket->ReAllocL(incoming));
       
   525 	if(err != KErrNone)
       
   526 		{
       
   527 		// We can't do anything here, so close & error
       
   528 		iMuxChannel->Close();
       
   529 		MuxChannelError(ETrue, err);
       
   530 		}
       
   531 	else
       
   532 		{
       
   533 		TDblQueIter<CRfcommSAP> iter(iSAPs);
       
   534 		CRfcommSAP* sap;
       
   535 		
       
   536 		while(iter)
       
   537 			{
       
   538 			sap=iter++;
       
   539 			sap->MuxUp();
       
   540 			}
       
   541 		iter=iBlockedSAPs;
       
   542 		while(iter)
       
   543 			{
       
   544 			sap=iter++;
       
   545 			sap->MuxUp();
       
   546 			}
       
   547 		}
       
   548 	}
       
   549  
       
   550 void CRfcommMuxer::Disconnect()
       
   551 	/**
       
   552 	   The L2CAP link has disconnected.
       
   553 
       
   554 	   
       
   555 	**/
       
   556 	{
       
   557 	iMuxChannel->Disconnect();
       
   558 	}
       
   559 
       
   560 void CRfcommMuxer::Disconnect(TDesC8& /*aDisconnectData*/)
       
   561 	{
       
   562 	Disconnect();
       
   563 	}
       
   564 
       
   565 void CRfcommMuxer::IoctlComplete(TDesC8* aBuf)
       
   566 	/**
       
   567 	   An ioctl has completed.
       
   568 
       
   569 	   Broadcast it to all the saps that might be interested
       
   570 	**/
       
   571 	{
       
   572 	PropagateIoctlCompletion(KErrNone, iIoctlLevel, iIoctlName, aBuf);
       
   573 	iIoctlName=0;
       
   574 	iIoctlLevel=0;
       
   575 	}
       
   576 
       
   577 void CRfcommMuxer::PropagateIoctlCompletion(TInt aError, TUint aIoctlLevel, TUint aIoctlName, TDesC8* aBuf)
       
   578 	{
       
   579 	TDblQueIter<CRfcommSAP> iter(iSAPs);
       
   580 	CRfcommSAP* sap;
       
   581 	while(iter)
       
   582 		{
       
   583 		sap=iter++;
       
   584 		sap->IoctlComplete(aError, aIoctlLevel, aIoctlName, aBuf);
       
   585 		}
       
   586 	iter=iBlockedSAPs;
       
   587 	while(iter)
       
   588 		{
       
   589 		sap=iter++;
       
   590 		sap->IoctlComplete(aError, aIoctlLevel, aIoctlName, aBuf);
       
   591 		}
       
   592 	}
       
   593 
       
   594 void CRfcommMuxer::ConnectComplete()
       
   595 	/**
       
   596 	   Signal from bound sap that connection has occurred.
       
   597 	   
       
   598 	   Part of the MSocketNotify interface. This is called when L2CAP
       
   599 	   has brought up the lower layer link to the remote device.
       
   600 	   Pass this through to the muxchannel.
       
   601 	**/
       
   602 	{
       
   603 	FTRACE(TSockAddr addr;
       
   604 		   iBoundSAP->RemName(addr);
       
   605 		   LOG1(_L("RFCOMM: Connect complete rcid %d"),
       
   606 		   	  addr.Port());
       
   607 		   iBoundSAP->LocalName(addr);
       
   608 		   LOG1(_L("RFCOMM: Connect complete lcid %d"),
       
   609 		   	  addr.Port());
       
   610 		);
       
   611 	iMuxChannel->ConnectComplete();
       
   612 	}
       
   613 
       
   614 /**********************************************************************/
       
   615 /*
       
   616   Commands from the SAP.
       
   617 */
       
   618 
       
   619 TUint8 CRfcommMuxer::MakeDLCI(TUint8 aServerChannel, TUint8 aDirectionBit)
       
   620 	{
       
   621 	TUint8 addr = aServerChannel;
       
   622 	addr <<= 1;
       
   623 	addr |= aDirectionBit;
       
   624 	return addr;
       
   625 	}
       
   626 
       
   627 TUint8 CRfcommMuxer::MakeOutboundDLCI(TUint8 aServerChannel)
       
   628 	/**
       
   629 	 Given a server channel, add the direction bit for an outbound connection
       
   630 	 **/
       
   631 	{
       
   632 	// Use the inverse of our direction bit
       
   633 	return MakeDLCI(aServerChannel, ~iDirection & KDirectionMask);
       
   634 	}
       
   635 	
       
   636 TUint8 CRfcommMuxer::MakeInboundDLCI(TUint8 aServerChannel)
       
   637 	/**
       
   638 	 Given a server channel, add the direction bit for an inbound connection
       
   639 	 **/
       
   640 	{
       
   641 	return MakeDLCI(aServerChannel, iDirection);
       
   642 	}
       
   643 	
       
   644 TUint8 CRfcommMuxer::MakeServerChannel(TUint8 aDLCI)
       
   645 	/**
       
   646 	Given a DLCI, turn that back into a server channel
       
   647 	**/
       
   648 	{
       
   649 	return aDLCI>>1;	//	Lose the bottom (direction) bit.
       
   650 	}
       
   651 
       
   652 TInt CRfcommMuxer::GetMaxDataSize() const
       
   653 	/**
       
   654 	   Returns the current max data size allowed
       
   655 	**/
       
   656 	{
       
   657 	return iMuxChannel->MaxDataSize();
       
   658 	}
       
   659 
       
   660 
       
   661 void CRfcommMuxer::Donate(CRfcommSAP& aSAP, TUint8 aCredit)
       
   662 	/**
       
   663 	   Send an empty UIH data frame, cos the other end has been caught short
       
   664 	**/
       
   665 	{
       
   666 	//Try to find another "Donate" frame in the outbound Q and attach to that...
       
   667 	TDblQueIter<CRfcommFrame> iter(iOutboundQ);
       
   668 	CRfcommFrame* frmInQ;
       
   669 	
       
   670 	while(iter)
       
   671 		{
       
   672 		frmInQ=iter;
       
   673  		if(frmInQ->Ctrl()==KUIHCBFCCtrlField && !(frmInQ->DataLength()))
       
   674  		    {
       
   675  		    if (frmInQ->SAP() && 
       
   676  		       (frmInQ->SAP()->RemoteAddress() == aSAP.RemoteAddress() && 
       
   677  		       (frmInQ->SAP()->DLCI()) == aSAP.DLCI()))
       
   678  		        {
       
   679                 LOG1(_L("RFCOMM: Old credit in donate frame: %d"), frmInQ->Credit());
       
   680                 TUint8 revisedDonation = aCredit+frmInQ->Credit();
       
   681                 frmInQ->SetCredit(revisedDonation);
       
   682                 LOG1(_L("RFCOMM: New credit in donate frame: %d"), frmInQ->Credit());
       
   683                 break;
       
   684  			}
       
   685 		}
       
   686 		iter++;
       
   687 		}
       
   688 
       
   689 	if(!iter)
       
   690 		//If no other "Donate" frame in the outbound Q.....
       
   691 		{
       
   692 		CRfcommDataFrame* frm=0;
       
   693 		
       
   694 		frm=NewDataFrame(aSAP.DLCI(), 0, aCredit, &aSAP);
       
   695 		if(!frm)
       
   696 			{
       
   697 			LOG1(_L("RFCOMM: OOM when writing for SAP %08x, queueing SAP Error callback"), &aSAP);
       
   698 			aSAP.iErrorKicker->SetError(KErrNoMemory, CRfcommSAP::EErrorOperation);
       
   699 			aSAP.iErrorKicker->Call();
       
   700 			}
       
   701 		if(!frm)
       
   702 			{
       
   703 			SetSendBlocked(aSAP, ETrue);
       
   704 			return;
       
   705 			}
       
   706 		
       
   707 		EnqueFrame(frm);
       
   708 		}
       
   709 
       
   710 	FlowStrategy()->ReviseDonatedCredits(aSAP, aCredit); //Rx credit
       
   711 	}
       
   712 
       
   713 TInt CRfcommMuxer::Write(CRfcommSAP& aSAP, TUint8 aCredit, const TDesC8& aData)
       
   714 	/**
       
   715 	   Write some data.
       
   716 
       
   717 	   We attempt to create a datapacket on the Q for this packet.  If
       
   718 	   this fails or the data Q is too long then we return less than
       
   719 	   the length of the data.  In which case we mark the SAP as
       
   720 	   needing a CanSend, and provide one at a suitable later date.
       
   721 	**/
       
   722 	{
       
   723 	__ASSERT_DEBUG(aData.Length() <= iMuxChannel->MaxDataSize(), Panic(ERfcommDataTooLong));
       
   724 	CRfcommDataFrame* frm=0;
       
   725 
       
   726 	if(iOutboundQLength < KMaxOutboundQLength)
       
   727 		{
       
   728 		frm=NewDataFrame(aSAP.DLCI(), aData.Length(), aCredit, &aSAP);
       
   729 
       
   730 		if(!frm)
       
   731 			{
       
   732 			LOG1(_L("RFCOMM: OOM when writing for SAP %08x, queueing SAP Error callback"), &aSAP);
       
   733 			aSAP.iErrorKicker->SetError(KErrNoMemory, CRfcommSAP::EErrorOperation);
       
   734 			aSAP.iErrorKicker->Call();
       
   735 			}
       
   736 		}
       
   737 	
       
   738 
       
   739 	if(!frm)
       
   740 		{
       
   741 		SetSendBlocked(aSAP, ETrue);
       
   742 		return 0;
       
   743 		}
       
   744 	if(!aData.Length())
       
   745 		{
       
   746 		LOG(_L("RFCOMM: Write has sent ZERO length data."));
       
   747 		}
       
   748 
       
   749 	frm->PutData(aData);
       
   750 	LOG1(_L("RFCOMM: Writing 0x%x"),/*frm->Data()*/aData[0]);
       
   751 	//BLOG: (KBlogWriteData, aData[0])
       
   752 	
       
   753 	FlowStrategy()->ReviseTransmittedCredits(aSAP); //TxCredit
       
   754 	FlowStrategy()->ReviseDonatedCredits(aSAP, aCredit); //Rx credit
       
   755 	EnqueFrame(frm);
       
   756 	return aData.Length();
       
   757 	}
       
   758 
       
   759 TInt CRfcommMuxer::Ioctl(TUint aLevel, TUint aName, TDes8* aOption)
       
   760 	/**
       
   761 	   A request to do an ioctl onto our lower level sap.
       
   762 	   
       
   763 	   If one's already in progress, simply return KErrInUse
       
   764 	**/
       
   765 	{
       
   766 	if(iIoctlLevel)
       
   767 		{
       
   768 		return KErrInUse;
       
   769 		}
       
   770 	else
       
   771 		{
       
   772 		iIoctlLevel=aLevel;
       
   773 		iIoctlName=aName;
       
   774 		iBoundSAP->Ioctl(aLevel, aName, aOption);
       
   775 		}
       
   776 	return KErrNone;
       
   777 	}
       
   778 
       
   779 void CRfcommMuxer::CancelIoctl(TUint aLevel, TUint aName)
       
   780 	/**
       
   781 	One of the RFCOMM SAPs has been asked to cancel an Ioctl which
       
   782 	was being run at the L2CAP level.
       
   783 	**/
       
   784 	{
       
   785 	if(aLevel==iIoctlLevel && iIoctlName==aName)
       
   786 		{
       
   787 		iBoundSAP->CancelIoctl(aLevel, aName);
       
   788 		iIoctlLevel=0;
       
   789 		iIoctlName=0;
       
   790 		}
       
   791 	}
       
   792 
       
   793 TInt CRfcommMuxer::SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption)
       
   794 	// Handle SetOption passed down from SAP
       
   795 	{
       
   796 	return iBoundSAP->SetOption(aLevel, aName, aOption);
       
   797 	}
       
   798 
       
   799 TInt CRfcommMuxer::GetOption(TUint aLevel, TUint aName, TDes8 &aOption)
       
   800 	// Handle SetOption passed down from SAP
       
   801 	{
       
   802 	return iBoundSAP->GetOption(aLevel, aName, aOption);
       
   803 	}
       
   804 		
       
   805 void CRfcommMuxer::SetCanHandleData(CRfcommSAP& aSAP, TBool aCanReceive)
       
   806 	/**
       
   807 	   Inform the muxer whether this sap can handle more data arriving.
       
   808 
       
   809 	   The mux uses this information to see if it is safe to read more
       
   810 	   data up from L2CAP.
       
   811 	   
       
   812 	   @param aCanReceive False if this sap can't handle any more
       
   813 	**/
       
   814 	{
       
   815 	LOG2(_L("RFCOMM: CanHandleData sap %08x, State %d"),
       
   816 				  &aSAP, aCanReceive);
       
   817 		
       
   818 	//FC
       
   819 	// Update the bitmask that controls whether we will take new data from L2CAP
       
   820 	SetNoFreeSpace(aSAP.DLCI(), !aCanReceive);
       
   821 	
       
   822 	if(CanProcessNewData() && iPacketsWaiting)
       
   823 		{
       
   824 		NewData(0);  // Tickle ourselves
       
   825 		}
       
   826 	}
       
   827 
       
   828 TInt CRfcommMuxer::SendSABM(CRfcommSAP& aSAP)
       
   829 	/**
       
   830 	   Send a SABM for this SAP
       
   831 	**/
       
   832 	{
       
   833 	LOG2(_L("RFCOMM: SendSABM for SAP %08x, Addr %d"), &aSAP, aSAP.DLCI());
       
   834 	return(TransmitSABM(aSAP.DLCI(), &aSAP));
       
   835 	}
       
   836 
       
   837 TInt CRfcommMuxer::SendMSC(CRfcommSAP& aSAP, TUint8 aFlags)
       
   838 	/**
       
   839 	   Send a MSC command for this SAP.
       
   840 	**/
       
   841 	{
       
   842 	//FC
       
   843 	LOG1(_L("RFCOMM: Sending MSC command for sap %08x"), &aSAP);
       
   844 	return TransmitMSC(aSAP.DLCI(), ETrue, aFlags, &aSAP);
       
   845 	}
       
   846 
       
   847 TInt CRfcommMuxer::SendMSCRsp(CRfcommSAP& aSAP, TUint8 aFlags)
       
   848 	/**
       
   849 	   Send a MSC response for this SAP.
       
   850 	**/
       
   851 	{
       
   852 	LOG1(_L("RFCOMM: Sending MSC response for sap %08x"), &aSAP);
       
   853 	return TransmitMSC(aSAP.DLCI(), EFalse, aFlags, &aSAP);
       
   854 	}
       
   855 
       
   856 TInt CRfcommMuxer::SendRLS(CRfcommSAP& aSAP, TUint8 aStatus)
       
   857 	/**
       
   858 	   Send a Remote Line Status command for this SAP.
       
   859 	**/
       
   860 	{
       
   861 	LOG1(_L("RFCOMM: Sending RLS cmd for sap %08x"), &aSAP);
       
   862 	return TransmitRLS(ETrue, aSAP.DLCI(), aStatus, &aSAP);
       
   863 	}
       
   864 
       
   865 TInt CRfcommMuxer::SendRLSRsp(CRfcommSAP& aSAP, TUint8 aStatus)
       
   866 	/**
       
   867 	   Send a Remote Line Status response for this SAP.
       
   868 	**/
       
   869 	{
       
   870 	LOG1(_L("RFCOMM: Sending RLS resp for sap %08x"), &aSAP);
       
   871 	return TransmitRLS(EFalse, aSAP.DLCI(), aStatus, &aSAP);
       
   872 	}
       
   873 
       
   874 TInt CRfcommMuxer::SendRPN(CRfcommSAP& aSAP, TBool aCommand, TUint8 aLength, 
       
   875 						   const TRfcommRPNTransaction& aRPNTransaction)
       
   876 	/**
       
   877 	   Send a RPN frame to L2CAP for this SAP.
       
   878 	**/
       
   879 	{
       
   880 	return TransmitRPN(aSAP.DLCI(), aCommand, aLength, aRPNTransaction, &aSAP);
       
   881 	}
       
   882 
       
   883 TInt CRfcommMuxer::SendUA(CRfcommSAP& aSAP)
       
   884 	/**
       
   885 	   Send a UA frame on behalf of the SAP
       
   886 	**/
       
   887 	{
       
   888 	return TransmitUA(aSAP.DLCI(), &aSAP);
       
   889 	}
       
   890 
       
   891 TInt CRfcommMuxer::SendUA(TUint8 aDLCI)
       
   892 	/**
       
   893 	   Send a UA frame on for the DLC
       
   894 	**/
       
   895 	{
       
   896 	return TransmitUA(aDLCI);
       
   897 	}
       
   898 
       
   899 TInt CRfcommMuxer::SendPN(CRfcommSAP& aSAP, const TRfcommPortParams& aParams)
       
   900 	/**
       
   901 	   Send a PN frame on behalf of the SAP
       
   902 	   This function takes the proposed maximum frame size parameter from the SAP itself.
       
   903 	**/
       
   904 	{
       
   905 	return TransmitPN(aSAP.DLCI(), ETrue, aParams, &aSAP);
       
   906 	}
       
   907 
       
   908 TInt CRfcommMuxer::SendPNResponse(CRfcommSAP& aSAP, const TRfcommPortParams& aParams)
       
   909 	/**
       
   910 		Send a PN Response frame on behalf of the SAP
       
   911 	**/
       
   912 	{
       
   913 	return TransmitPN(aSAP.DLCI(), EFalse, aParams, &aSAP);
       
   914 	}
       
   915 
       
   916 void CRfcommMuxer::SendDISC(CRfcommSAP& aSAP)
       
   917 	/**
       
   918 	   Disconnect this sap and associated DLC.
       
   919 	**/
       
   920 	{
       
   921 	TransmitDISC(aSAP.DLCI(), &aSAP);
       
   922 	}
       
   923 
       
   924 void CRfcommMuxer::SendDISC(TUint8 aDLCI)
       
   925 	/**
       
   926 	   Disconnect the associated DLC.
       
   927 	**/
       
   928 	{
       
   929 	TransmitDISC(aDLCI);
       
   930 	}
       
   931 
       
   932 void CRfcommMuxer::SendDM(TUint8 aDLCI)
       
   933 	{
       
   934 	TransmitDM(aDLCI,ETrue);
       
   935 	}
       
   936 
       
   937 TInt CRfcommMuxer::SendFCon()
       
   938 	/**
       
   939 	Sends a FCon command to the peer RFCOMM entity.
       
   940 
       
   941 	Used only for internal testing purposes.
       
   942 	**/
       
   943 	{
       
   944 	//FC
       
   945 	return TransmitFCon(ETrue,NULL);
       
   946 	}
       
   947 
       
   948 TInt CRfcommMuxer::SendFCoff()
       
   949 	/**
       
   950 	Sends a FCoff command to the peer RFCOMM entity.
       
   951 
       
   952 	Used only for internal testing purposes.
       
   953 	**/
       
   954 	{
       
   955 	//FC
       
   956 	return TransmitFCoff(ETrue,NULL);
       
   957 	}
       
   958 
       
   959 /*
       
   960   Timeout from the frames
       
   961 */
       
   962 
       
   963 void CRfcommMuxer::FrameResponseTimeout(CRfcommFrame* aFrm)
       
   964 	/*
       
   965 	  Called when a frame that needs a response times out
       
   966 
       
   967 	*/
       
   968 	{
       
   969 	//	I could code the next bit more efficiently, but don't like obfuscation!
       
   970 	TBool done=EFalse;
       
   971 	if(aFrm->SAP()!=NULL)
       
   972 		done=aFrm->SAP()->HandleFrameResponseTimeout();
       
   973 
       
   974 	if(!done)
       
   975 		iMuxChannel->FrameTimeout(aFrm);
       
   976 	//	The frame will be cleaned up either by the mux error handling or by the SAP 
       
   977 	//	going into the closed or error state.
       
   978 	}
       
   979 
       
   980 void CRfcommMuxer::ClearOutboundQueue(CRfcommSAP& aSAP)
       
   981 	/**
       
   982 	   Clear any frames on the outbound queue that point to this SAP.
       
   983 
       
   984 	   This prevents any frame timeout getting back to a deleted SAP.
       
   985 	   If a SAP wants to send a frame to the remote end after its
       
   986 	   death, it must make sure that the iSAP member of the frame does
       
   987 	   not point to it (ie is null).
       
   988 	**/
       
   989 	{
       
   990 	TDblQueIter<CRfcommFrame> iter(iOutboundQ);
       
   991 	CRfcommFrame* frm;
       
   992 	
       
   993 	while(iter)
       
   994 		{
       
   995 		frm=iter++;
       
   996 		if(frm->SAP() == &aSAP)
       
   997 			{
       
   998 			--iOutboundQLength;
       
   999 			delete frm;
       
  1000 			}
       
  1001 		}
       
  1002 	}
       
  1003 
       
  1004 void CRfcommMuxer::ClearResponseQueue(CRfcommSAP& aSAP)	
       
  1005 	/**
       
  1006 	Clear the response queue of all frames associated with the SAP.
       
  1007 
       
  1008 	The association is based on the frame pointing to the sap, or
       
  1009 	being for a DLCI which matches that of the SAP.  Frames on DLCI 0
       
  1010 	are not matched by the DLCI matching.
       
  1011 	
       
  1012 	This is generally called in response to a SAP being closed or
       
  1013 	entering an error state.  Clearly since the sap is no longer
       
  1014 	around, it makes no sense to keep the frames that are awaiting a
       
  1015 	response for timeout purposes.
       
  1016 	**/
       
  1017 	{
       
  1018 	TDblQueIter<CRfcommFrame> iter(iResponseQ);
       
  1019 	CRfcommFrame* frm=NULL;
       
  1020 	TUint8 frmDLCI=KMuxDLCI;
       
  1021 
       
  1022 	TUint8 dlci=aSAP.iDLCI;
       
  1023 	if(dlci == KMuxDLCI)
       
  1024 		dlci=KMaxRfcommDLCI+1;  // This is an impossible DLCI that will never match
       
  1025 	while(iter)
       
  1026 		{
       
  1027 		frm=iter++;
       
  1028 		
       
  1029 		//	determine the DLCI the frame is associated with
       
  1030 		if(frm->Type() == KMuxCtrlFrameType)
       
  1031 			frmDLCI=static_cast<CRfcommMuxCtrlFrame*>(frm)->DLCI();
       
  1032 		else
       
  1033 			frmDLCI=frm->Address();
       
  1034 
       
  1035 		if(frmDLCI==dlci || frm->SAP() == &aSAP)
       
  1036 			{
       
  1037 			LOG2(_L("RFCOMM: Clearing response for DLCI %d, sap 0x%08x"), frmDLCI, &aSAP);
       
  1038 			delete frm;
       
  1039 			break;
       
  1040 			}
       
  1041 		}
       
  1042 	}
       
  1043 
       
  1044 /**********************************************************************/
       
  1045 /*
       
  1046   Internal functions.
       
  1047 */
       
  1048 
       
  1049 void CRfcommMuxer::SetNoFreeSpace(TInt aDLCI, TBool aVal)
       
  1050 	/**
       
  1051 		Sets or resets this DLCI as having no space
       
  1052 
       
  1053 		@param aVal   True if no space
       
  1054 	**/
       
  1055 	{
       
  1056 	__ASSERT_DEBUG(aDLCI <= KMaxRfcommDLCI, Panic(ERfcommInvalidDLCI));
       
  1057 	if(aVal)
       
  1058 		iSAPNoFreeSpaceMask[aDLCI >> 5] |= 1 << (aDLCI % 32);
       
  1059 	else
       
  1060 		iSAPNoFreeSpaceMask[aDLCI >> 5] &= ~(1 << (aDLCI % 32));
       
  1061 	}
       
  1062 
       
  1063 TBool CRfcommMuxer::CanProcessNewData() const
       
  1064 	{
       
  1065 	return iFlowStrategy->CanProcessNewData(!iSAPNoFreeSpaceMask[0] && !iSAPNoFreeSpaceMask[1]);
       
  1066 	}
       
  1067 
       
  1068 void CRfcommMuxer::SetSendBlocked(CRfcommSAP& aSAP, TBool aIsBlocked)
       
  1069 	/**
       
  1070 	   Mark the state of this SAP as able/unable to send
       
  1071 
       
  1072 	   This is done by moving the SAP from the active to the blocked
       
  1073 	   Q.  To ensure all saps get a chance, we wake saps from the
       
  1074 	   front of the blocked Q, but add them to the end, thus
       
  1075 	   round-robining the chance to send.
       
  1076 	**/
       
  1077 	{
       
  1078 	
       
  1079 	aSAP.iLink.Deque();
       
  1080 	if(aIsBlocked)
       
  1081 		/*AddFirst - this helps avoid an infinite loop.
       
  1082 		For example SignalSAPsCanSend() unblocks a SAP 
       
  1083 		then can cause it to be reblocked when it calls 
       
  1084 		sap->CanSend().
       
  1085 		*/
       
  1086 		iBlockedSAPs.AddFirst(aSAP); 
       
  1087 	else
       
  1088 		iSAPs.AddLast(aSAP);
       
  1089 	}
       
  1090 
       
  1091 void CRfcommMuxer::ProcessFrame()
       
  1092 	/**
       
  1093 	   Process the frame that is at the start data buffer.
       
  1094 
       
  1095 	   When this is called, a frame is in the data buffer.  The
       
  1096 	   contents should be verified and processed appropriately.
       
  1097 	**/
       
  1098 	{
       
  1099 	if(iNextPacket->Length() < KMinFrameLength)
       
  1100 		{
       
  1101 		LOG(_L("RFCOMM:  ** ERROR ** received frame too short"));
       
  1102 		return;
       
  1103 		}
       
  1104 	LOG(_L("1st five bytes of incoming frame...."));
       
  1105 	LOGHEXRAW(&(*iNextPacket)[0], 5);
       
  1106 	
       
  1107 	TUint8  addr=DecodeDLCI((*iNextPacket)[KFrameAddrOffset]);
       
  1108 	TUint8  ctrl=(*iNextPacket)[KFrameCtrlOffset];
       
  1109 	// Is this really necessary ?
       
  1110 	TBool   poll = ((ctrl & KPollFinalBitmask) != 0)?ETrue:EFalse;
       
  1111 	//TBool   poll = ctrl & KPollFinalBitmask;
       
  1112 	ctrl = static_cast<TUint8>(ctrl & ~KPollFinalBitmask); // zero the poll/final bit
       
  1113 
       
  1114 	//LOG1(_L("RFCOMM: Frame for dlci %d"), addr);
       
  1115 	if(addr!=0 && !iMuxChannel->IsOpen())
       
  1116 		{
       
  1117 		LOG1(_L("RFCOMM: Error: Frame for dlci %d before mux channel up - junking"), addr);
       
  1118 		return;
       
  1119 		}
       
  1120 	DecodeLengthAndCredit((poll && ctrl == KUIHCtrlField && addr != KMuxDLCI));  // get the length and the credit if correct packet
       
  1121 
       
  1122 	// Frame length is header+data+fcs (fcs is one byte)
       
  1123 	if(iCurrentDataLength+iCurrentHeaderLength+1 != iNextPacket->Length())
       
  1124 		{
       
  1125 		if(iCurrentDataLength+iCurrentHeaderLength+1 < iNextPacket->Length())
       
  1126 			{
       
  1127 			LOG(_L("RFCOMM: Frame shorter than L2CAP packet, junking"));
       
  1128 			}
       
  1129 		else
       
  1130 			{
       
  1131 			LOG(_L("RFCOMM: Frame longer than L2CAP packet, junking"));
       
  1132 			}
       
  1133 		return;
       
  1134 		}
       
  1135 	
       
  1136 	TUint8  fcs=(*iNextPacket)[iCurrentDataLength+iCurrentHeaderLength];
       
  1137 		
       
  1138 	if(CheckFCS(fcs,ctrl))
       
  1139 		{
       
  1140 	switch (ctrl)
       
  1141 			{
       
  1142 		case KSABMCtrlField:
       
  1143 			if(poll)
       
  1144 				{
       
  1145 				LOG(_L("Rx: SABM"));
       
  1146 				HandleSABM(addr);
       
  1147 				}
       
  1148 			else
       
  1149 				{
       
  1150 				// Must ignore SABM with poll bit 0, TS07.10 5.4.4.1
       
  1151 				LOG(_L("RFCOMM: SABM with P/F = 0, ignoring"));
       
  1152 				}
       
  1153 			break;
       
  1154 			
       
  1155 		case KUACtrlField:
       
  1156 			LOG(_L("Rx: UA"));
       
  1157 			HandleUA(addr);
       
  1158 			break;
       
  1159 			
       
  1160 		case KDMCtrlField:
       
  1161 			LOG(_L("Rx: DM"));
       
  1162 			HandleDM(addr);
       
  1163 			break;
       
  1164 			
       
  1165 		case KDISCCtrlField:
       
  1166 			if(poll)
       
  1167 				{
       
  1168 				LOG(_L("Rx: DISC"));
       
  1169 				HandleDISC(addr);
       
  1170 				}
       
  1171 			else
       
  1172 				{
       
  1173 				// Must ignore DISC with poll bit 0, TS07.10 5.4.4.1
       
  1174 				LOG(_L("RFCOMM: DISC with P/F = 0, ignoring"));
       
  1175 				}
       
  1176 			break;
       
  1177 			
       
  1178 		case KUIHCtrlField:
       
  1179 			if(addr == KMuxDLCI)
       
  1180 				{
       
  1181 				LOG(_L("Rx: UIH Ctrl Frame"));
       
  1182 				TRAPD(err, ParseCtrlMessageL());
       
  1183 				if(err !=KErrNone)
       
  1184 					{
       
  1185 					LOG(_L("RFCOMM: Error in parsing the ctrl frames"));
       
  1186 					}
       
  1187 				}
       
  1188 			else
       
  1189 				{
       
  1190 				LOG(_L("Rx: Simple UIH"));
       
  1191 				ProcessDataFrame(addr, poll);
       
  1192 				}
       
  1193 			break;
       
  1194 			
       
  1195 		default:
       
  1196 			{
       
  1197 			LOG(_L("Error: RFCOMM: Unexpected frame ctrl field"));
       
  1198 			}
       
  1199 			}
       
  1200 		}
       
  1201 	else
       
  1202 		{
       
  1203 		LOG(_L("RFCOMM: Frame failed checksum"));
       
  1204 		}
       
  1205 	}
       
  1206 
       
  1207 TUint8 CRfcommMuxer::DecodeDLCI(TUint8 aAddr)
       
  1208 	/**
       
  1209 	   Strip off the EA and C/R bits and return an TS07.10 DLCI.
       
  1210 
       
  1211 	   Note that this is not the same as the RFCOMM server channel,
       
  1212 	   which is 5 bits + 1 direction bit.
       
  1213 	**/
       
  1214 	{
       
  1215 	return TUint8(aAddr >> 2);
       
  1216 	}
       
  1217 
       
  1218 void CRfcommMuxer::DecodeLengthAndCredit(TBool aCBFC)
       
  1219 	/**
       
  1220 	   Decode the length of a frame.
       
  1221 
       
  1222 	   Return the overall length of the header.  This can be one or
       
  1223 	   two bytes in length.
       
  1224 	**/
       
  1225 	{
       
  1226 	if((*iNextPacket)[2] & 1)
       
  1227 		{
       
  1228 		// Single byte length
       
  1229 		iCurrentDataLength=(*iNextPacket)[2] >> 1;
       
  1230 		iCurrentHeaderLength= KShortFrameHeaderLength;
       
  1231 		}
       
  1232 	else 
       
  1233 		{
       
  1234 		iCurrentDataLength=((*iNextPacket)[2] >> 1) +
       
  1235 			((*iNextPacket)[3] << 7);
       
  1236 		iCurrentHeaderLength= KLongFrameHeaderLength;
       
  1237 		}
       
  1238 
       
  1239 	//if doing CBFC updates credit buffer and revises header length buffer
       
  1240 	//(iCurrentHeaderLength and iCurrentCredit)
       
  1241 	iFlowStrategy->DecodeLength(aCBFC, *iNextPacket, 
       
  1242 						iCurrentCredit, iCurrentHeaderLength);
       
  1243 	}
       
  1244 
       
  1245 void CRfcommMuxer::HandleSABM(TUint8 aDLCI)
       
  1246 	/**
       
  1247 		Handles an incoming SABM command.
       
  1248 		This function basically dispatches the SABM to either the
       
  1249 		mux channel or an appropriate SAP.
       
  1250 	**/
       
  1251 	{
       
  1252 	if(iCurrentDataLength != 0)
       
  1253 		{
       
  1254 		LOG1(_L("RFCOMM: SABM frame with length %d"), iCurrentDataLength);
       
  1255 		}
       
  1256 // want this for UPF test verification - need the whole of a SABM in log file	
       
  1257 	LOG1(_L("RFCOMM: SABM command received, DLCI %d"), aDLCI);
       
  1258 	LOGHEXRAW(&((iNextPacket->Des())[0]), (iCurrentHeaderLength+iCurrentDataLength));
       
  1259 	
       
  1260 	if(aDLCI == KMuxDLCI)
       
  1261 		//	A SABM intended to initialise the Mux channel
       
  1262 		iMuxChannel->SABM();
       
  1263 	else
       
  1264 		{
       
  1265 		//	A SABM intended for a SAP
       
  1266 		CRfcommSAP* mySAP=FindConnectedOrListeningSAP(aDLCI);
       
  1267 		if(mySAP)
       
  1268 			mySAP->SABM(*this, aDLCI);
       
  1269 		else
       
  1270 			{
       
  1271 			//	There is nothing out there to handle this SABM.
       
  1272 			//	Send a DM back as response.
       
  1273 			SendDM(aDLCI);
       
  1274 			}
       
  1275 		}
       
  1276 	}
       
  1277 
       
  1278 void CRfcommMuxer::HandleDISC(TUint8 aAddr)
       
  1279 	/**
       
  1280 	   Handles an incoming DISConnect request.
       
  1281 
       
  1282 	   If this is for the mux channel then we should shutdown totally.
       
  1283 	   Otherwise we signal the appropriate SAP and then send a UA
       
  1284 	   frame to acknowledge.
       
  1285 	**/
       
  1286 	{
       
  1287 	LOG1(_L("RFCOMM: DISC frame for DLCI %d"), aAddr);
       
  1288 	if(iCurrentDataLength !=0)
       
  1289 		{
       
  1290 		LOG(_L("RFCOMM: DISC frame length !=0"));
       
  1291 		}
       
  1292 
       
  1293 	CRfcommSAP* sap;
       
  1294 	
       
  1295 	if(aAddr != KMuxDLCI)
       
  1296 		{
       
  1297 		sap=FindSAP(aAddr);
       
  1298 		if(!sap)
       
  1299 			{
       
  1300 			LOG(_L("RFCOMM: DISC for non-existant sap"));
       
  1301 			TransmitDM(aAddr, ETrue);
       
  1302 			}
       
  1303 		else
       
  1304 			{
       
  1305 			sap->DISC();
       
  1306 			}
       
  1307 		}
       
  1308 	else
       
  1309 		{
       
  1310 		iMuxChannel->DISC();
       
  1311 		}
       
  1312 	}
       
  1313 
       
  1314 void CRfcommMuxer::HandleDM(TUint8 aAddr)
       
  1315 	/**
       
  1316 	   Handles an incoming DM frame.
       
  1317 
       
  1318 	   We must remove the equivalent SABM or DISC from the response Q
       
  1319 	**/
       
  1320 	{
       
  1321 	LOG1(_L("RFCOMM: DM Frame for DLCI %d"), aAddr);
       
  1322 	if(aAddr != KMuxDLCI)
       
  1323 		{
       
  1324 		CRfcommSAP* sap=FindSAP(aAddr);
       
  1325 		if(!sap)
       
  1326 			{
       
  1327 			LOG(_L("RFCOMM: DM for unanticipated DLCI!"));
       
  1328 			}
       
  1329 		else
       
  1330 			{
       
  1331 			sap->DM();
       
  1332 			}
       
  1333 		}
       
  1334 	else
       
  1335 		{
       
  1336 		iMuxChannel->DM();
       
  1337 		}
       
  1338 	if(!CtrlFrameResponse(aAddr))
       
  1339 		MuxCtrlResponseDM(aAddr);
       
  1340 	}
       
  1341 
       
  1342 void CRfcommMuxer::HandleUA(TUint8 aAddr)
       
  1343 	/**
       
  1344 	   Handles an incoming UA frame.
       
  1345 
       
  1346 	   This represents an acknowledgement of a command on this channel.
       
  1347 	**/
       
  1348 	{
       
  1349 	LOG1(_L("RFCOMM: UA Frame for addr %d"), aAddr);
       
  1350 	if(aAddr != KMuxDLCI)
       
  1351 		{
       
  1352 		CRfcommSAP* sap=FindSAP(aAddr);
       
  1353 		if(!sap)
       
  1354 			{
       
  1355 			LOG(_L("RFCOMM: UA for invalid DLCI, ignoring"));
       
  1356 			}
       
  1357 		else
       
  1358 			{
       
  1359 			sap->UA();
       
  1360 			}
       
  1361 		}
       
  1362 	else
       
  1363 		{
       
  1364 		iMuxChannel->UA();
       
  1365 		}
       
  1366 	//	Attempt to find the matching control frame - ignore errors.
       
  1367 	(void)CtrlFrameResponse(aAddr);
       
  1368 	}
       
  1369 
       
  1370 // TRY_CBFC is this used for PNresponses ? got to check if our CBFC overture has been
       
  1371 // accepted. Appears only to be used for DM and UA responses where no action is needed
       
  1372 TInt CRfcommMuxer::CtrlFrameResponse(TUint8 aAddr)
       
  1373 	/**
       
  1374 	   Remove the ctrl frame that caused this response from the response pending Q
       
  1375 
       
  1376 	   Responses are UA and DM, which may both be caused by SABM &
       
  1377 	   DISC frames.  However, there should only ever be one SABM/DISC
       
  1378 	   outstanding for a given address, so we simply look for a
       
  1379 	   matching address.
       
  1380 	**/
       
  1381 	{
       
  1382 	TDblQueIter<CRfcommFrame> iter(iResponseQ);
       
  1383 	CRfcommFrame* frm;
       
  1384 
       
  1385 	while(iter)
       
  1386 		{
       
  1387 		frm=iter++;
       
  1388 		if(frm->Type() == KCtrlFrameType && DecodeDLCI(frm->Address()) == aAddr)
       
  1389 			{
       
  1390 			LOG(_L("RFCOMM: Found matching Ctrl command for response"));
       
  1391 			delete frm;
       
  1392 			break;
       
  1393 			}
       
  1394 		}
       
  1395 	return(iter?KErrNone:KErrNotFound);
       
  1396 	}
       
  1397 
       
  1398 void CRfcommMuxer::ProcessDataFrame(TUint8 aAddr, TBool aPoll)
       
  1399 	/**
       
  1400 	   Send this data up to the sap.
       
  1401 	**/
       
  1402 	{
       
  1403 	__ASSERT_DEBUG(iNextPacket, Panic(ERfcommNoPacket));
       
  1404 	LOG(_L("CRfcommMuxer::ProcessDataFrame"));
       
  1405 	CRfcommSAP* sap=FindSAP(aAddr);
       
  1406 	if(sap)
       
  1407 		{
       
  1408 		if(iFlowStrategy->ProcessDataFrameReviseCredits(*sap, aPoll, iCurrentCredit))
       
  1409 			//returning'ETrue' => sap needs unblocking
       
  1410 			{
       
  1411 			LOG(_L("RFCOMM: CBFC unblocking"));
       
  1412 			SetSendBlocked(*sap, EFalse);
       
  1413 			sap->CanSend();
       
  1414 			}
       
  1415 		if (iCurrentDataLength)
       
  1416 			{
       
  1417 			sap->Data(iNextPacket->Mid(iCurrentHeaderLength, iCurrentDataLength));
       
  1418 			}
       
  1419 		else
       
  1420 			{
       
  1421 			LOG(_L("RFCOMM: Data frame with no data - probably a CBFC credit"));
       
  1422 			}
       
  1423 		}
       
  1424 	else
       
  1425 		{
       
  1426 		LOG1(_L("RFCOMM: Data for unknown sap %d"), aAddr);
       
  1427 		}
       
  1428 	}
       
  1429 
       
  1430 void CRfcommMuxer::ParseCtrlMessageL()
       
  1431 	/**
       
  1432 	   Parse the control messages for the mux.
       
  1433 
       
  1434 	   The data on the channel has the following format.
       
  1435 
       
  1436 	   | Type | Length | Value 1 | Value 2 | ... | Value n |
       
  1437 	   unless this is PN frame then CL bits may indicate CBFC
       
  1438 	   and the K bits indicate the initial credit
       
  1439 
       
  1440 	**/
       
  1441 	{
       
  1442 	TInt offset=0; // Number of bytes we've parsed.
       
  1443 	TInt x=0;
       
  1444 	TUint8 type=0;
       
  1445 	TInt length;
       
  1446 	TBool command;  // command or response
       
  1447 
       
  1448 	if(!iMuxChannel->IsOpen())
       
  1449 		{
       
  1450 		LOG(_L("RFCOMM: Error - mux ctrl message before muxchannel open! Junking."));
       
  1451 //		return;  // MB - fixme
       
  1452 		}
       
  1453 	
       
  1454 	while(offset+2 <= iCurrentDataLength)
       
  1455 		{
       
  1456 		command=(*iNextPacket)[iCurrentHeaderLength+offset] & KCRBitmask;
       
  1457 		offset+=GetTypeFieldL(x, offset);
       
  1458 		// Type must be 8 bits or less for us to deal with
       
  1459 		if(x > 255 || x < 0)
       
  1460 			{
       
  1461 			User::Leave(KErrArgument);
       
  1462 			}
       
  1463 		type=static_cast<TUint8>(x);
       
  1464 		offset+=GetLengthFieldL(length, offset);
       
  1465 		if(offset+length > iCurrentDataLength)
       
  1466 			{
       
  1467 			User::Leave(KErrArgument);
       
  1468 			}
       
  1469 		
       
  1470 		LOG2(_L("RFCOMM: Incoming Packet, %d, %d"),type, length);
       
  1471 
       
  1472 		// Now parse the individual types.  Offset points to the data
       
  1473 		switch(type)
       
  1474 			{
       
  1475 		case KTestType:
       
  1476 			HandleTest(command, iCurrentHeaderLength+offset, length);
       
  1477 			break;
       
  1478 		
       
  1479 		case KFConType:
       
  1480 			//FC
       
  1481 			if(length!=0)
       
  1482 				{
       
  1483 				LOG(_L("RFCOMM: FCon with non-zero length!"));
       
  1484 				}
       
  1485 			HandleFCon(command);
       
  1486 			//
       
  1487 			break;
       
  1488 		
       
  1489 		case KFCoffType:
       
  1490 			//FC
       
  1491 			if(length!=0)
       
  1492 				{
       
  1493 				LOG(_L("RFCOMM: FCoff with non-zero length!"));
       
  1494 				}
       
  1495 			HandleFCoff(command);
       
  1496 			//
       
  1497 			break;
       
  1498 
       
  1499 		case KMSCType:
       
  1500 			{
       
  1501 			LOG(_L("RFCOMM: MSC:"));
       
  1502 			LOGHEXRAW(&((iNextPacket->Des())[0]), (iCurrentHeaderLength+iCurrentDataLength));
       
  1503 
       
  1504 			LOG2(_L("RFCOMM: MSC Hex: Incoming Packet, %d, %d"), (*iNextPacket)[0], 80);
       
  1505 			
       
  1506 			// See TS 7.10, pg 29 for details
       
  1507 			// Length must be exactly 2, or 3 if 'Break Signals' are present
       
  1508 			if(length < 2 || length > 3)
       
  1509 				{
       
  1510 				LOG1(_L("RFCOMM: MSC with erroneous length %d"), length);
       
  1511 				break;
       
  1512 				}
       
  1513 			// Next byte is DLCI...
       
  1514 			TUint8 dlci = static_cast<TUint8>((*iNextPacket)[iCurrentHeaderLength+offset] >> 2);
       
  1515 			LOG1(_L("RFCOMM: DLCI %d"), dlci);
       
  1516 			// ...and the next is the V.24 signals
       
  1517 			TUint8 signals = static_cast<TUint8>((*iNextPacket)[iCurrentHeaderLength+offset+1] >> 1);
       
  1518 			LOG3(_L("RFCOMM: MSC %S received dlci %d signals 0x%02x"),
       
  1519 				(command?&KCommandText:&KResponseText), dlci, signals);
       
  1520 			
       
  1521 			if(!command)
       
  1522 				{
       
  1523 				LOG(_L("RFCOMM: Response"));
       
  1524 				}
       
  1525 			else
       
  1526 				{
       
  1527 				LOG(_L("RFCOMM: Command"));
       
  1528 				}
       
  1529 			LOG1(_L("RFCOMM: Signals 0x%02x"), signals);
       
  1530 
       
  1531 			HandleMSC(command, dlci, signals);
       
  1532 			break;
       
  1533 			}
       
  1534 
       
  1535 		case KRPNType:
       
  1536 		    {
       
  1537 			// RPN frame received from L2CAP
       
  1538 			LOG(_L("RFCOMM: RPN received"));
       
  1539 			if(length != KRPNRequestLength && 
       
  1540 			   length != KRPNCommandLength &&
       
  1541 			   length != KRPNResponseLength)
       
  1542 				{
       
  1543 				LOG(_L("RFCOMM: Ignoring RPN with bad length"));
       
  1544 				break;
       
  1545 				}
       
  1546 			TUint8 dlci=0;
       
  1547 			if(length == KRPNRequestLength)
       
  1548 				{
       
  1549 				// There's no parameter data
       
  1550 				ParseRPN(iCurrentHeaderLength+offset, length, dlci);
       
  1551 				HandleRPN(command, dlci); 
       
  1552 				}
       
  1553 			else // There was data so need to parse this too
       
  1554 				{
       
  1555 				TRfcommRPNTransaction rpnTransaction;
       
  1556 				ParseRPN(iCurrentHeaderLength+offset, length, dlci, 
       
  1557 						 &rpnTransaction);
       
  1558 				HandleRPN(command, dlci, &rpnTransaction);
       
  1559 				}
       
  1560 			break;
       
  1561 			}
       
  1562 
       
  1563 		case KPNType:
       
  1564 		    {
       
  1565 			LOG(_L("RFCOMM: PN received"));
       
  1566 			LOGHEXRAW(&((iNextPacket->Des())[0]), (iCurrentHeaderLength+iCurrentDataLength));
       
  1567 
       
  1568 			TRfcommPortParams portparams;
       
  1569 			TUint8 dlci;
       
  1570 			ParsePNL(iCurrentHeaderLength+offset, length, dlci, portparams);
       
  1571 			HandlePN(command, dlci, portparams);
       
  1572 			break;
       
  1573 			}
       
  1574 		
       
  1575 		case KNSCType:
       
  1576 			LOG(_L("RFCOMM: NSC received"));
       
  1577 			break;
       
  1578 
       
  1579 		case KRLSType:
       
  1580 			{
       
  1581 			LOG(_L("RFCOMM: RLS received"));
       
  1582 			// See TS 7.10, pgs 34/35 for details
       
  1583 			const TUint8 KRLSLength = 2; // Length *must* be exactly 2
       
  1584 			if(length != KRLSLength)
       
  1585 				{
       
  1586 				LOG1(_L("RFCOMM: RLS with erroneous length %d"),
       
  1587 							  length);
       
  1588 				break;
       
  1589 				}
       
  1590 			// First byte is DLCI...
       
  1591 			TUint8 dlci = TUint8((*iNextPacket)[iCurrentHeaderLength+offset]) >> 2;
       
  1592 			// ...and the next is the status octet
       
  1593 			TUint8 status = TUint8((*iNextPacket)[iCurrentHeaderLength+offset+1]);
       
  1594 			LOG3(_L("RFCOMM: RLS %S received dlci %d status 0x%02x"),
       
  1595 					(command?&KCommandText:&KResponseText), dlci, status);
       
  1596 			HandleRLS(command, dlci, status);
       
  1597 			break;		
       
  1598 			}
       
  1599 		default:
       
  1600 			LOG1(_L("RFCOMM: Unknown type 0x%02x"), type);
       
  1601 			TransmitNSC(command, type);
       
  1602 			break;
       
  1603 			}
       
  1604 		offset+=length;
       
  1605 		}
       
  1606 	}
       
  1607 
       
  1608 void CRfcommMuxer::ParsePNL(TInt aOffset, TInt aLen, TUint8& aDLCI,
       
  1609 						    TRfcommPortParams& aParams)
       
  1610 	/**
       
  1611 	   Parse the PN field at the specified offset in the frame.
       
  1612 	   Format is:
       
  1613 	   @verbatim
       
  1614 	   Value Octet Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
       
  1615 	       1        D1    D2    D3    D4    D5    D6    0     0
       
  1616     	   2        I1    I2    I3    I4    CL1   CL2   CL3   CL4
       
  1617 	       3        P1    P2    P3    P4    P5    P6    0     0
       
  1618     	   4        T1    T2    T3    T4    T5    T6    T7    T8
       
  1619     	   5        N1    N2    N3    N4    N5    N6    N7    N8
       
  1620 	       6        N9    N10   N11   N12   N13   N14   N15   N16
       
  1621     	   7        NA1   NA2   NA3   NA4   NA5   NA6   NA7   NA8
       
  1622      	   8        K1    K2    K3    0     0     0     0     0
       
  1623 
       
  1624 	   Where:
       
  1625 	     D1-6  : DLCI
       
  1626 		 I1-4  : frame type (must be zero)
       
  1627 		 CL1-4 : Convergence layer (if CBFC 0xf for command, 0xe for response...
       
  1628 									...otherwise must be zero)
       
  1629 		 P1-6  : Priority
       
  1630 		 T1-8  : Acknowledgement timer T1 (must be zero)
       
  1631 		 N1-16 : Max frame size (default 127)
       
  1632 		 NA1-8 : Max retransmissions (must be zero)
       
  1633 		 K1-3  : either Initial CBFC credit or Error recovery window (must be zero)
       
  1634 		 @endverbatim
       
  1635 	**/
       
  1636 	{
       
  1637 	// Length must be exactly 8
       
  1638 	const TUint8 KPNLength = 8;
       
  1639 	if(aLen < KPNLength)
       
  1640 		{
       
  1641 		LOG(_L("RFCOMM: Invalid PN packet length"));
       
  1642 		User::Leave(KErrGeneral);
       
  1643 		}
       
  1644 
       
  1645 	HBufC8& packet = *iNextPacket;
       
  1646 
       
  1647 	// Constants for offsets into packet
       
  1648 	// DLCI is at start of byte, (offset = 0)
       
  1649 	// Ignore frame type		 (offset = 1)
       
  1650 	const TUint8 KConvergenceLayerOffset = 1; //used by CBFC
       
  1651 	const TUint8 KPriorityOffset		 = 2;
       
  1652 	// Ignore Ack timer			 (offset = 3)
       
  1653 	const TUint8 KMaxFrameLowerOffset	 = 4;
       
  1654 	const TUint8 KMaxFrameUpperOffset	 = 5;
       
  1655 	const TUint8 KErrorRecoveryWindow    = 7; //used by CBFC
       
  1656 	// Ignore the rest
       
  1657 
       
  1658 	// DLCI - only want lowest 6 bits of byte
       
  1659 	aDLCI = packet[aOffset] & KMaxRfcommDLCI;
       
  1660 	// Priority - only want lowest 6 bits of byte
       
  1661 	aParams.iPriority = packet[aOffset+KPriorityOffset] & 0x3f;
       
  1662 	// Frame size is 2 bytes. Lower byte first...
       
  1663 	aParams.iMaxFrameSize = TUint16(packet[aOffset+KMaxFrameLowerOffset]);
       
  1664 	// ...then upper byte
       
  1665 	aParams.iMaxFrameSize += TUint16(packet[aOffset+KMaxFrameUpperOffset] << 8);
       
  1666 	aParams.iCreditIndicator = TUint8(packet[aOffset + KConvergenceLayerOffset] >> 4);
       
  1667 	aParams.iInitialCredit = TUint8(packet[aOffset + KErrorRecoveryWindow] & 7);
       
  1668 	LOG2(_L("RFCOMM: PN Rx(CBFC) CL 0x%02x, K 0x%02x"), aParams.iCreditIndicator, aParams.iInitialCredit);
       
  1669 	}
       
  1670 
       
  1671 void CRfcommMuxer::ParseRPN(TInt aOffset, TInt aLen, TUint8& aDLCI, 
       
  1672 							TRfcommRPNTransaction* aRPNTransactionPtr)
       
  1673 	/**
       
  1674 
       
  1675 	Parse an incoming RPN frame.  
       
  1676 	aOffset points to the start of the data octets on entry
       
  1677 
       
  1678 	@verbatim
       
  1679 	Format is:
       
  1680 	Value Octet Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
       
  1681 	     0       EA    1               DLCI
       
  1682 		 1       B1    B2    B3    B4    B5    B6    B7    B8
       
  1683 		 2       D1    D2    S     P     PT1   PT2   res   res
       
  1684 		 3       FLC1  FLC2  FLC3  FLC4  FLC5  FLC6  res   res
       
  1685 		 4       XON1  XON2  XON3  XON4  XON5  XON6  XON7  XON8
       
  1686 		 5       XOF1  XOF2  XOF3  XOF4  XOF5  XOF6  XOF7  XOF8
       
  1687 		 6       PM1   PM2   PM3   PM4   PM5   PM6   PM7   PM8
       
  1688 		 7       PM9   PM10  PM11  PM12  PM13  PM14  PM15  PM16
       
  1689 
       
  1690 	Where:
       
  1691 	   B1-8   :  Baud rate
       
  1692        D1-2   :  data bits
       
  1693 	   S      :  Stop bits
       
  1694 	   P      :  Parity
       
  1695 	   PT1-2  :  Parity Type
       
  1696 	   FLC1-6 :  Flow ctrl type
       
  1697 	   XON1-8 :  Xon character
       
  1698 	   XOFF1-8:  Xoff character
       
  1699 	   PM1-16 :  Which values are to be set/accepted
       
  1700    @endverbatim
       
  1701 	See TS07.10 5.4.6.3.9 for more details
       
  1702 	**/
       
  1703 	{
       
  1704 	// Wrap a descriptor over the data we want
       
  1705 	TPtrC8 valueOctets=iNextPacket->Des().Mid(aOffset, aLen);
       
  1706 	
       
  1707 	// Get the DLCI
       
  1708 	aDLCI = valueOctets[0] >> 2;
       
  1709 	LOG1(_L("RFCOMM: RPN frame, DLCI %d"), aDLCI);
       
  1710 
       
  1711 	// Now parse out the valid fields if necessary
       
  1712 	if(aRPNTransactionPtr)
       
  1713 		{
       
  1714 		LOG(_L("Parsing full RPN data\n"));
       
  1715 		// Local references into the transaction structure
       
  1716 		TRfcommRemotePortParams& portParams = aRPNTransactionPtr->iPortParams;
       
  1717 		TUint16& paramMask = aRPNTransactionPtr->iParamMask;
       
  1718 		// construct the parameter mask out of the last two value octets
       
  1719 		paramMask = TUint16(valueOctets[7]);
       
  1720 		paramMask = TUint16((paramMask << 8) + valueOctets[6]);
       
  1721 		
       
  1722 		// Bit rate
       
  1723 		if(paramMask & EPMBitRate)
       
  1724 		{
       
  1725 			TUint8 bitRate=valueOctets[1];
       
  1726 			switch(bitRate)
       
  1727 			{
       
  1728 			// Magic numbers because enums are not the same 
       
  1729 			// values as the ones specified in the spec and 
       
  1730 			// adding even more enums would confuse matters
       
  1731 			case 0:
       
  1732 				portParams.SetBitRate(EBps2400);
       
  1733 				break;
       
  1734 			case 1:
       
  1735 				portParams.SetBitRate(EBps4800);
       
  1736 				break;
       
  1737 			case 2:
       
  1738 			case 3:
       
  1739 			case 4:
       
  1740 			case 5:
       
  1741 			case 6:
       
  1742 			case 7:
       
  1743 			case 8:
       
  1744 				portParams.SetBitRate(static_cast<TBps>(EBps7200+(bitRate-2)));
       
  1745 				break;
       
  1746 			default:
       
  1747 				{
       
  1748 				LOG(_L("RFCOMM: RPN with invalid bitrate field, ignoring"));
       
  1749 				}
       
  1750 			}
       
  1751 		}
       
  1752 		
       
  1753 		// Value octet 2 is compound
       
  1754 		// Masks for bit position within octet
       
  1755 		//							Bit number:	   76543210
       
  1756 		const TUint8 KDataBitsPos		= 0x03; // 000000XX
       
  1757 		const TUint8 KStopBitPos		= 0x04;	// 00000X00
       
  1758 		const TUint8 KParityBitPos		= 0x08;	// 0000X000
       
  1759 		const TUint8 KParityTypeBitsPos = 0x30; // 00XX0000
       
  1760 		// 2 most significant bits are reserved (always 0)
       
  1761 
       
  1762 		const TUint8 KStopBitOffset		= 2; // offset for 00000X00
       
  1763 		const TUint8 KParityBitOffset	= 3; // offset for 0000X000
       
  1764 		const TUint8 KParityTypeOffset	= 4; // offset for 00XX0000
       
  1765 			
       
  1766 		if(paramMask & EPMDataBits)
       
  1767 			{
       
  1768 			TUint8 dataBits = TUint8(valueOctets[2] & KDataBitsPos);
       
  1769 			// Data bits
       
  1770 			switch(dataBits)
       
  1771 				{
       
  1772 				// Magic numbers because enums are not the same 
       
  1773 				// values as the ones specified in the spec and 
       
  1774 				// adding even more enums would confuse matters
       
  1775 				case 0:
       
  1776 					portParams.SetDataBits(EData5);
       
  1777 					break;
       
  1778 				case 1:
       
  1779 					portParams.SetDataBits(EData7);
       
  1780 					break;
       
  1781 				case 2:
       
  1782 					portParams.SetDataBits(EData6);
       
  1783 					break;
       
  1784 				case 3:
       
  1785 					portParams.SetDataBits(EData8);
       
  1786 					break;
       
  1787 				default:
       
  1788 					__DEBUGGER()
       
  1789 					LOG(_L("How did we get more than 3 with 2 bits?!\n"));
       
  1790 				}
       
  1791 			}
       
  1792 
       
  1793 		if(paramMask & EPMStopBit)
       
  1794 			{
       
  1795 			TUint8 stopBit = TUint8((valueOctets[2] & KStopBitPos)>>KStopBitOffset);
       
  1796 			portParams.SetStopBit(static_cast<TStopBits>(stopBit));
       
  1797 			}
       
  1798 
       
  1799 		// The Parity and ParityType bits have a combined effect..
       
  1800 		
       
  1801 		if(paramMask & EPMParity)
       
  1802 			{
       
  1803 			TUint8 parityBit = TUint8((valueOctets[2] & KParityBitPos)>>KParityBitOffset);
       
  1804 			
       
  1805 			if(!parityBit)
       
  1806 				{ 
       
  1807 				portParams.SetParity(EParityNone);
       
  1808 				}
       
  1809 			}
       
  1810 
       
  1811 		if(paramMask & EPMParityType)
       
  1812 			{
       
  1813 			TParity parityType = EParitySpace; //Just to stop the compiler warnings
       
  1814 
       
  1815 			//It is intended that this 'GetParity' will only update 'parityType' 
       
  1816 			//if 'SetParity' was called in the previous 'if' clause.
       
  1817 			portParams.GetParity(parityType);
       
  1818 
       
  1819 			if(parityType == EParityNone)
       
  1820 				{
       
  1821 				// Can't have a parity type if there's no parity set
       
  1822 				LOG(_L("RFCOMM: WARNING!: Tried to set parity type when parity is none or invalid"));
       
  1823 				}
       
  1824 			else
       
  1825 				{	
       
  1826 				// Parity Type is in first two bits of upper nibble
       
  1827 				// Need to move it down to the lower nibble
       
  1828 				switch((valueOctets[2] & KParityTypeBitsPos)>>KParityTypeOffset)
       
  1829 					{
       
  1830 				case 0:
       
  1831 					portParams.SetParity(EParityOdd);
       
  1832 					break;
       
  1833 				case 1:
       
  1834 					portParams.SetParity(EParityMark);
       
  1835 					break;
       
  1836 				case 2:
       
  1837 					portParams.SetParity(EParityEven);
       
  1838 					break;
       
  1839 				case 3:
       
  1840 					portParams.SetParity(EParitySpace);
       
  1841 					break;
       
  1842 				default:
       
  1843 					break;
       
  1844 					}
       
  1845 				}
       
  1846 			}
       
  1847 
       
  1848 		if(paramMask & EPMXOnChar)
       
  1849 			{
       
  1850 			portParams.SetXOnChar(valueOctets[4]);
       
  1851 			}
       
  1852 
       
  1853 		if(paramMask & EPMXOffChar)
       
  1854 			{
       
  1855 			portParams.SetXOffChar(valueOctets[5]);
       
  1856 			}	
       
  1857 
       
  1858 		// Flow control is only in the first 6 bits of this value octet
       
  1859 		TUint8 flowCtrl = TUint8(valueOctets[3] & 0x3f);
       
  1860 		portParams.UpdateWholeFlowCtrl(paramMask, flowCtrl);
       
  1861 		}
       
  1862 	else
       
  1863 		{	
       
  1864 		LOG(_L("Query request received - package has not been filled out\n"));
       
  1865 		}
       
  1866 	}
       
  1867 
       
  1868 
       
  1869 void CRfcommMuxer::HandleRLS(TBool aCommand, TUint8 aDLCI, TUint8 aStatus)
       
  1870 	/**
       
  1871 		Handle a RLS frame from remote dev
       
  1872 
       
  1873 		If it's a command, respond then pass the data up to the user
       
  1874 		If it's a response, just ignore it - it'll just be what we sent
       
  1875 	**/
       
  1876 	{
       
  1877 	CRfcommSAP* sap=FindSAP(aDLCI);
       
  1878 	if(!sap)
       
  1879 		{
       
  1880 		LOG1(_L("RFCOMM: RLS for unknown dlci %d"), aDLCI);
       
  1881 		if(aCommand)
       
  1882 			SendDM(aDLCI);
       
  1883 		return;
       
  1884 		}
       
  1885 
       
  1886 	if(aCommand)
       
  1887 		{
       
  1888 		LOG(_L("RFCOMM: RLS command received"));
       
  1889 		// Send a response to the remote device
       
  1890 		SendRLSRsp(*sap, aStatus);
       
  1891 		// Pass status up to the user
       
  1892 		sap->RLS(aStatus); 
       
  1893 		}
       
  1894 	else
       
  1895 		{
       
  1896 		// Response to our command
       
  1897 		LOG(_L("RFCOMM: RLS response received"));
       
  1898 		MuxCtrlResponse(KRLSType);
       
  1899 		}
       
  1900 	}
       
  1901 
       
  1902 
       
  1903 void CRfcommMuxer::HandleRPN(const TBool& aCommand, const TUint8& aDLCI, 
       
  1904 							 const TRfcommRPNTransaction* aRPNTransactionPtr)
       
  1905 	/**
       
  1906 	   Handle an RPN frame from remote dev
       
  1907 
       
  1908 	   If it's valid, just pass it on to the SAP
       
  1909 	**/
       
  1910 	{	
       
  1911 	LOG1(_L("RFCOMM: Handling RPN for dlci %d"), aDLCI);
       
  1912 
       
  1913 	if(aDLCI == KMuxDLCI)
       
  1914 		{
       
  1915 		LOG(_L("RFCOMM: RPN for Mux channel. Ignoring"));
       
  1916 		return;
       
  1917 		}
       
  1918 
       
  1919 	if(!aCommand && aRPNTransactionPtr == 0)
       
  1920 		{
       
  1921 		LOG(_L("RFCOMM: Corrupt RPN response. Ignoring"));
       
  1922 		return;
       
  1923 		}
       
  1924 	
       
  1925 	// Check to see if there's a sap to pass this onto
       
  1926 	CRfcommSAP* sap=FindConnectedOrListeningSAP(aDLCI);
       
  1927 	
       
  1928 	if(sap == 0)// No listening or connected SAP available
       
  1929 		{
       
  1930 		if(aCommand)
       
  1931 			{
       
  1932 			LOG(_L("RFCOMM: RPN command for unknown sap - Sending DM"));
       
  1933 			SendDM(aDLCI);
       
  1934 			}
       
  1935 		else
       
  1936 			{
       
  1937 			LOG(_L("RFCOMM: RPN response for unknown sap. Ignoring"));
       
  1938 			}
       
  1939 		return;
       
  1940 		}
       
  1941 
       
  1942 	// Still here? Everything's OK to pass the RPN on to the SAP
       
  1943 	if(aCommand)
       
  1944 		sap->RPN(aRPNTransactionPtr, *this, aDLCI);
       
  1945 	else // It's a valid response
       
  1946 		{
       
  1947 		// So we're no longer waiting for a response
       
  1948 		MuxCtrlResponse(KRPNType);
       
  1949 		sap->RPNRsp(*aRPNTransactionPtr);
       
  1950 		}
       
  1951 	}
       
  1952 
       
  1953 void CRfcommMuxer::HandlePN(TBool aCommand, TUint8 aDLCI, TRfcommPortParams& aParams)
       
  1954 	/**
       
  1955 	   Handles PN commands & responses.
       
  1956 	   
       
  1957 	   Hands over to the SAP, but checks the max length first and
       
  1958 	   truncates if necessary before passing on.  We may also get a PN
       
  1959 	   for the mux channel, which is setting the frame size.
       
  1960 	**/
       
  1961 	{
       
  1962 	LOG2(_L("RFCOMM: Handling PN for dlci %d (MTU=%d)"), aDLCI, aParams.iMaxFrameSize);
       
  1963 	if(aDLCI == KMuxDLCI)
       
  1964 		{
       
  1965 		iMuxChannel->PN(aCommand, aParams);
       
  1966 		}
       
  1967 	else
       
  1968 		{
       
  1969 		CRfcommSAP* sap=FindConnectedOrListeningSAP(aDLCI);
       
  1970 		TBool useCBFC = aCommand?(aParams.iCreditIndicator == (KCBFCCommandFlag >> 4)):
       
  1971 								 (aParams.iCreditIndicator == (KCBFCResponseFlag >> 4));
       
  1972 		if(!sap)
       
  1973 			{
       
  1974 			if(aCommand)
       
  1975 				{
       
  1976 				//	Means no suitable listening SAP is around.
       
  1977 				LOG(_L("RFCOMM: PN for unknown sap - incoming connection request with no listening SAP"));
       
  1978 				TransmitDM(aDLCI, ETrue);	//	DM for specified DLCI with P/F bit set
       
  1979 				}
       
  1980 			else
       
  1981 				{
       
  1982 				// unexpected response
       
  1983 				LOG(_L("RFCOMM: PN response for unknown sap, ignoring"));
       
  1984 				}
       
  1985 			}
       
  1986 		else
       
  1987 			{// Found a SAP for this PN
       
  1988 			if (!iTriedCBFC)
       
  1989 				{
       
  1990 				if(useCBFC)
       
  1991 					{
       
  1992 					SetFlowType(CRfcommFlowStrategyFactory::EFlowCreditBased);
       
  1993 					}
       
  1994 				else
       
  1995 					{
       
  1996 					SetFlowType(CRfcommFlowStrategyFactory::EFlowNonCreditBased);
       
  1997 					}
       
  1998 				}
       
  1999 
       
  2000 			if(aParams.iCreditIndicator == (KCBFCCommandFlag >> 4))
       
  2001 			//done for each PN
       
  2002 				{
       
  2003 				// need to set a one time initial credit in case
       
  2004 				// subsequent DLCs don't have a PN frame
       
  2005 				iInitialTxCredit = aParams.iInitialCredit;
       
  2006 				}
       
  2007 
       
  2008 			if(aCommand)
       
  2009 				{
       
  2010 				sap->PN(aParams,*this,aDLCI);
       
  2011 				}
       
  2012 			else
       
  2013 				{
       
  2014 				sap->PNResp(aParams);
       
  2015 				}
       
  2016 			}
       
  2017 		}
       
  2018 	// FIXME not sure about this, 
       
  2019 	// if this is a SAP PN frame will it be in the muxctrl queue ?
       
  2020 	if(!aCommand)
       
  2021 		MuxCtrlResponse(KPNType);
       
  2022 	}
       
  2023 
       
  2024 
       
  2025 void CRfcommMuxer::HandleMSC(TBool aCommand, TUint8 aDLCI, TUint8 aSignals)
       
  2026 	/**
       
  2027 		Handles a MSC command & response from the remote device
       
  2028 	   
       
  2029 		If it's a command, send response and filter up to SAP
       
  2030 		If it's a response, we're no longer expecting a response (!)
       
  2031 	**/
       
  2032 	{
       
  2033 	CRfcommSAP* sap=FindSAP(aDLCI);
       
  2034 	if(aCommand)
       
  2035 		{
       
  2036 		LOG(_L("RFCOMM: MSC command received"));
       
  2037 		if(sap)
       
  2038 			{
       
  2039 			// Send a response to remote device
       
  2040 			SendMSCRsp(*sap, aSignals);
       
  2041 			// Pass signals up to user
       
  2042 			sap->MSC(aSignals); 
       
  2043 			}
       
  2044 		else
       
  2045 			{
       
  2046 			LOG1(_L("RFCOMM: MSC for unknown dlci %d"), aDLCI);
       
  2047 			SendDM(aDLCI);
       
  2048 			}
       
  2049 		}
       
  2050 	else
       
  2051 		{ 
       
  2052 		LOG(_L("RFCOMM: MSC response received"));
       
  2053 		MuxCtrlResponse(KMSCType);
       
  2054 		}
       
  2055 	}
       
  2056 
       
  2057 void CRfcommMuxer::HandleTest(TBool aCommand, TInt aOffset, TInt aLen)
       
  2058 	/**
       
  2059 	   Handles a test command.
       
  2060 
       
  2061 	   If this is a command, then respond with the same data bytes as
       
  2062 	   were sent to us.  Else ignore it.
       
  2063 	**/
       
  2064 	{
       
  2065 	if(aCommand)
       
  2066 		{
       
  2067 		LOG(_L("RFCOMM: Test command received"));
       
  2068 		__ASSERT_DEBUG(aLen < iMuxChannel->MaxDataSize(), Panic(ERfcommTestDataTooLong));
       
  2069 		TransmitTest(!aCommand, TPtr8(&iNextPacket->Des()[aOffset], aLen, aLen));
       
  2070 		}
       
  2071 	else
       
  2072 		{
       
  2073 		MuxCtrlResponse(KTestType);
       
  2074 		LOG(_L("RFCOMM: Test response received"));
       
  2075 		}
       
  2076 	}
       
  2077 
       
  2078 void CRfcommMuxer::HandleFCon(TBool aCommand)
       
  2079 	/**
       
  2080 	   Handle a FCon instruction.
       
  2081 
       
  2082 	   If this is a command, then we need to respond and set flow ctrl
       
  2083 	   to OK.  Otherwise it's a response to our FCon command, and we
       
  2084 	   can expect the remote end to start sending.
       
  2085 	**/
       
  2086 	{
       
  2087 	if(aCommand)
       
  2088 		{
       
  2089 		LOG(_L("RFCOMM: FCon command received"));
       
  2090 		if(ClearToSend())
       
  2091 			{
       
  2092 			LOG(_L("RFCOMM: Received FCon when state was ON"));
       
  2093 			}
       
  2094 		SetCanSend(ETrue);
       
  2095 		if(TransmitFCon(EFalse) != KErrNone)
       
  2096 			{
       
  2097 			LOG(_L("RFCOMM: Failed to send FCon response!"));
       
  2098 			}
       
  2099 		TryToSend();  // Try to send even if we couldn't respond
       
  2100 		}
       
  2101 	else
       
  2102 		{
       
  2103 		LOG(_L("RFCOMM: FCon response received"));
       
  2104 		MuxCtrlResponse(KFConType);
       
  2105 		}
       
  2106 	}
       
  2107 
       
  2108 void CRfcommMuxer::HandleFCoff(TBool aCommand)
       
  2109 	/**
       
  2110 	   Handles a FCoff command.
       
  2111 
       
  2112 	   If this is a command, then set our state to flow ctrl off, and
       
  2113 	   send a response.  If it was a reply, then we should now not
       
  2114 	   expect any more data packets till we send a FCon.
       
  2115 	**/
       
  2116 	{
       
  2117 	//FC
       
  2118 	if(aCommand)
       
  2119 		{
       
  2120 		LOG(_L("RFCOMM: FCoff command received"));
       
  2121 		if(!ClearToSend())
       
  2122 			{
       
  2123 			LOG(_L("RFCOMM: Received FCoff when state was off"));
       
  2124 			}
       
  2125 		SetCanSend(EFalse);
       
  2126 		TransmitFCoff(EFalse);
       
  2127 		}
       
  2128 	else
       
  2129 		{
       
  2130 		LOG(_L("RFCOMM: FCoff response received"));
       
  2131 		MuxCtrlResponse(KFCoffType);
       
  2132 		}
       
  2133 	//
       
  2134 	}
       
  2135 
       
  2136 TInt CRfcommMuxer::GetTypeFieldL(TInt& aType, TInt aPos)
       
  2137 	/**
       
  2138 	   Parse the type field.  Due to EA bits this is of unknown length.
       
  2139 
       
  2140 	   Type field looks like this :
       
  2141 	   @verbatim
       
  2142        | EA | C/R | T1 | T2 | T3 | T4 | T5 | T6 |
       
  2143 
       
  2144 	   If EA is 0, then the following bytes are extensions:
       
  2145 
       
  2146 	   | EA | T7 | T8 | T9 | T10 | T11 | T12 | T13 |
       
  2147 	   @endverbatim
       
  2148 	   @param aType The type is returned in this
       
  2149 	   @param aPos  The start position in frame's data
       
  2150 	   @return The length of the type field in bytes.
       
  2151 	**/
       
  2152 	{
       
  2153 	const TUint8 KBitsInFirstTypeFieldByte = 6;
       
  2154 	const TUint8 KBitsInSubsequentTypeFieldBytes = 7;
       
  2155 	
       
  2156 	TInt readptr = iCurrentHeaderLength + aPos;
       
  2157 	aType = (*iNextPacket)[readptr] >> 2; // drop the EA and C/R bit (any good reason the latter?)
       
  2158 	TInt offset = 1; // in bytes
       
  2159 	TUint8 bitshift = KBitsInFirstTypeFieldByte;
       
  2160 	
       
  2161 	if(!((*iNextPacket)[readptr] & KEABitmask))
       
  2162 		{
       
  2163 		// Multiple length type field
       
  2164 		LOG(_L("RFCOMM: Multi-length type field in mux channel"));
       
  2165 		do
       
  2166 			{
       
  2167 			if(((readptr + offset - iCurrentHeaderLength) > iCurrentDataLength)
       
  2168 				|| ((bitshift + KBitsInSubsequentTypeFieldBytes) > KBitsForNumberInTInt))
       
  2169 				{
       
  2170 				// We enter here if the EA's are such that we cannot handle the field, by either
       
  2171 				// 1) They indicated there was another type field byte which isn't present.
       
  2172 				// 2) They indicate a type field value that cannot be represented in a TInt.
       
  2173 				User::Leave(KErrArgument);
       
  2174 				}
       
  2175 			// we should also check that we don't have too extensions
       
  2176 			// (i.e. we have a number larger than a TInt)
       
  2177 			aType += ((*iNextPacket)[readptr+offset] >> 1) << bitshift;
       
  2178 			offset++;
       
  2179 			bitshift += KBitsInSubsequentTypeFieldBytes;
       
  2180 			}
       
  2181 		while (!((*iNextPacket)[readptr+offset-1] & KEABitmask));
       
  2182 		}
       
  2183 	
       
  2184 	return offset;
       
  2185 	}
       
  2186 	
       
  2187 TInt CRfcommMuxer::GetLengthFieldL(TInt& aLen, TInt aPos)
       
  2188 	/**
       
  2189 	   Parse the length field.  Due to EA bits this is of unknown length.
       
  2190 
       
  2191 	   Type field looks like this :
       
  2192 
       
  2193        | EA | L1 | L2 | L3 | L4 | L5 | L6 | L7 |
       
  2194 
       
  2195 	   @param aLen The length is returned in this
       
  2196 	   @param aPos The start position in the frame's data
       
  2197 	   @return The length of the length field.
       
  2198 	**/
       
  2199 	{
       
  2200 	const TUint8 KBitsInLengthFieldByte = 7;
       
  2201 	
       
  2202 	TInt readptr = iCurrentHeaderLength + aPos;
       
  2203 	aLen = (*iNextPacket)[readptr] >> 1; // discard the EA bit
       
  2204 	TInt offset = 1;
       
  2205 	TUint8 bitshift = KBitsInLengthFieldByte;
       
  2206 	
       
  2207 	if(!((*iNextPacket)[readptr] & KEABitmask))
       
  2208 		{
       
  2209 		// Multiple length Len field
       
  2210 		LOG(_L("RFCOMM: Multi-length length field in mux channel"));
       
  2211 		do
       
  2212 			{
       
  2213 			// Initially we do some checking to ensure field isn't malformed.
       
  2214 			// Part 1 of 2.
       
  2215 			if((readptr + offset - iCurrentHeaderLength) > iCurrentDataLength)
       
  2216 				{
       
  2217 				// We enter here if the EAs indicate that there is another length field byte
       
  2218 				// when there isn't.
       
  2219                 User::Leave(KErrArgument);
       
  2220 				}
       
  2221 
       
  2222 			// Now we know that there is sufficient data in the packet, we can get the next length value
       
  2223 			TUint8 value((*iNextPacket)[readptr+offset] >> 1);
       
  2224 			
       
  2225 			// Do some more checking of the field
       
  2226 			// Part 2 of 2.
       
  2227 			if((bitshift + KBitsInLengthFieldByte) > KBitsForNumberInTInt)
       
  2228 				{
       
  2229 				// We enter here if the EA's indicate that the length value the field represents is
       
  2230 				// potentially larger than a TInt.
       
  2231 				// However it may be that the overflowed bits are just trailing zeros, meaning that
       
  2232 				// we can represent it.
       
  2233 				TUint8 trailingZeroMask(0xff);
       
  2234 				trailingZeroMask <<= (KBitsForNumberInTInt - bitshift);
       
  2235 				trailingZeroMask &= value;
       
  2236 				if(trailingZeroMask != 0x00)
       
  2237 					{
       
  2238 					// We enter here if there are bits which would overflow a TInt
       
  2239 					User::Leave(KErrArgument);
       
  2240 					}
       
  2241 				}
       
  2242 
       
  2243 			// If here the byte appears valid, so update the length as appropriate.
       
  2244 			aLen += value << bitshift;
       
  2245 			offset++;
       
  2246 			bitshift += KBitsInLengthFieldByte;
       
  2247 			}
       
  2248 		while (!((*iNextPacket)[readptr+offset-1] & KEABitmask));
       
  2249 		}
       
  2250 	
       
  2251 	return offset;
       
  2252 	}
       
  2253 
       
  2254 void CRfcommMuxer::MuxCtrlResponse(TUint8 aType)
       
  2255 	/**
       
  2256 	   Remove the mux ctrl frame that caused this response from the
       
  2257 	   response pending Q
       
  2258 
       
  2259 	   To fully match a response, one would need to look at all the
       
  2260 	   parameters to the command.  However, we cheat by just matching
       
  2261 	   the command type.  This may lead us to remove the wrong one,
       
  2262 	   but since any lack of a match brings down the link, we go for
       
  2263 	   the easy option.
       
  2264 	**/
       
  2265 	{
       
  2266 	TDblQueIter<CRfcommFrame> iter(iResponseQ);
       
  2267 	CRfcommFrame* frm;
       
  2268 
       
  2269 	while(iter)
       
  2270 		{
       
  2271 		frm=iter++;
       
  2272 		if(frm->Type() == KMuxCtrlFrameType)
       
  2273 			{
       
  2274 			CRfcommMuxCtrlFrame* muxframe=static_cast<CRfcommMuxCtrlFrame*>(frm);
       
  2275 			if(muxframe->CommandType() == aType)
       
  2276 				{
       
  2277 				LOG(_L("RFCOMM: Found matching muxctrl command for response"));
       
  2278 				delete frm;
       
  2279 				break;
       
  2280 				}
       
  2281 			}
       
  2282 		}
       
  2283 	}
       
  2284 
       
  2285 void CRfcommMuxer::MuxCtrlResponseDM(TUint8 aDLCI)
       
  2286 	/**
       
  2287 	   Remove the mux ctrl frame that caused this DM response from the
       
  2288 	   response pending Q
       
  2289 
       
  2290 	   All we have to work on is the DLCI of the channel which issued the
       
  2291 	   original mux control frame which elicited the DM response. We
       
  2292 	   can search through the response queue until we find a frame sent 
       
  2293 	   out for this DLCI.
       
  2294     **/
       
  2295 	{
       
  2296 	TDblQueIter<CRfcommFrame> iter(iResponseQ);
       
  2297 	CRfcommFrame* frm;
       
  2298 
       
  2299 	while(iter)
       
  2300 		{
       
  2301 		frm=iter++;
       
  2302 		if(frm->Type() == KMuxCtrlFrameType)
       
  2303 			{
       
  2304 			CRfcommMuxCtrlFrame* muxframe=static_cast<CRfcommMuxCtrlFrame*>(frm);
       
  2305 			if(muxframe->DLCI() == aDLCI)
       
  2306 				{
       
  2307 				LOG(_L("RFCOMM: Found matching muxctrl command for DM response"));
       
  2308 				delete frm;
       
  2309 				break;
       
  2310 				}
       
  2311 			}
       
  2312 		}
       
  2313 	}
       
  2314 
       
  2315 TInt CRfcommMuxer::TransmitSABM(TUint8 aDLCI, CRfcommSAP* aSAP)
       
  2316 	/**
       
  2317 	   Send a SABM command for specified DLCI.
       
  2318 	   This command is used to start the connection of a channel,
       
  2319 	   including the control channel.
       
  2320 	   @verbatim
       
  2321 	   Frame format is:
       
  2322 
       
  2323 	   Address | Control | Length | FCS
       
  2324 
       
  2325 	   Address format is:
       
  2326 
       
  2327 	   | 1  |  2  | 3 | 4   5   6   7   8 |
       
  2328 	   | EA | C/R | D |  Server channel   |
       
  2329 
       
  2330 	   Where aDLCI already includes the D & Server channel bits.
       
  2331 	   @endverbatim
       
  2332 
       
  2333 	   We always set the P/F bit to one in a SABM frame.
       
  2334 	   
       
  2335 	   @param aDLCI This value is the server channel plus direction
       
  2336 	   bit part of the DLCI.  This will have the E/A & C/R bits added.
       
  2337 
       
  2338 	   @return Error code
       
  2339 	**/
       
  2340 	{
       
  2341 	LOG1(_L("RFCOMM: Sending SABM for DLCI %d"), aDLCI); 
       
  2342 	CRfcommCtrlFrame* frm=NewFrame(aSAP);
       
  2343 	
       
  2344 	if(!frm)
       
  2345 		return KErrNoMemory;
       
  2346 
       
  2347 	frm->SetResponseNeeded(ETrue);
       
  2348 	frm->SetAddress(BuildAddr(aDLCI, ETrue));
       
  2349 	frm->SetControl(KSABMCtrlField | KPollFinalBitmask);
       
  2350 	/*
       
  2351 	BLOG: The frame has now been prepared therefore can show all bits. 
       
  2352 	//BLOG: Can show all the information about this frame in TrytoSend() just as it is physically about
       
  2353 	//to go over the air - Bluetooth...wooohooooo!
       
  2354 	//Mind you probably should blog DLCI here? 
       
  2355 	//BLOG KBlogDLCI
       
  2356 	BlogTransmitCtrlFrame(frm, aDLCI, aSAP)
       
  2357 	*/	
       
  2358 	EnqueFrame(frm);
       
  2359 	
       
  2360 	return KErrNone;
       
  2361 	}
       
  2362 
       
  2363 TInt CRfcommMuxer::TransmitUA(TUint8 aDLCI, CRfcommSAP* aSAP)
       
  2364 	{
       
  2365 	LOG1(_L("RFCOMM: Sending UA for DLCI %d"), aDLCI); 
       
  2366 	CRfcommCtrlFrame* frm=NewFrame(aSAP);
       
  2367 	if(!frm)
       
  2368 		return KErrNoMemory;
       
  2369 
       
  2370 	// UA always has Final set
       
  2371 	frm->SetControl(KUACtrlField | KPollFinalBitmask);
       
  2372 	frm->SetAddress(BuildAddr(aDLCI, EFalse));
       
  2373 	EnqueFrame(frm);
       
  2374 	return KErrNone;
       
  2375 	}
       
  2376 
       
  2377 TInt CRfcommMuxer::TransmitDM(TUint8 aDLCI, TBool aPFBit, CRfcommSAP* aSAP)
       
  2378 	{
       
  2379 	LOG1(_L("RFCOMM: Sending DM for DLCI %d"), aDLCI); 
       
  2380 	CRfcommCtrlFrame* frm=NewFrame(aSAP);
       
  2381 	if(!frm)
       
  2382 		return KErrNoMemory;
       
  2383 
       
  2384 	if(aPFBit)
       
  2385 		frm->SetControl(KDMCtrlField | KPollFinalBitmask);
       
  2386 	else
       
  2387 		frm->SetControl(KDMCtrlField);
       
  2388 	frm->SetAddress(BuildAddr(aDLCI, EFalse));
       
  2389 	EnqueFrame(frm);
       
  2390 	return KErrNone;
       
  2391 	}
       
  2392 
       
  2393 TInt CRfcommMuxer::TransmitDISC(TUint8 aDLCI, CRfcommSAP* aSAP)
       
  2394 	{
       
  2395 	LOG1(_L("RFCOMM: Sending DISC for DLCI %d"), aDLCI); 
       
  2396 	CRfcommCtrlFrame* frm=NewFrame(aSAP);
       
  2397 	if(!frm)
       
  2398 		return KErrNoMemory;
       
  2399 
       
  2400 	// DISC always has Final set
       
  2401 	frm->SetResponseNeeded(ETrue);
       
  2402 	frm->SetControl(KDISCCtrlField | KPollFinalBitmask);
       
  2403 	frm->SetAddress(BuildAddr(aDLCI, ETrue));  // C/R set
       
  2404 	EnqueFrame(frm);
       
  2405 	return KErrNone;
       
  2406 	}
       
  2407 
       
  2408 TInt CRfcommMuxer::TransmitRPN(TUint8 aDLCI, TBool aCommand, TUint8 aLen,
       
  2409 							   const TRfcommRPNTransaction& aRPNTransaction, CRfcommSAP* aSAP)
       
  2410 	/**
       
  2411 
       
  2412 	Transmit an RPN frame. 
       
  2413 
       
  2414 	@verbatim
       
  2415 	Format is:
       
  2416 	Value Octet Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
       
  2417 		 1		 E/A   C/R	---------------DLCI----------------
       
  2418 		 2       B1    B2    B3    B4    B5    B6    B7    B8
       
  2419 		 3       D1    D2    S     P     PT1   PT2   res   res
       
  2420 		 4       FLC1  FLC2  FLC3  FLC4  FLC5  FLC6  res   res
       
  2421 		 5       XON1  XON2  XON3  XON4  XON5  XON6  XON7  XON8
       
  2422 		 6       XOF1  XOF2  XOF3  XOF4  XOF5  XOF6  XOF7  XOF8
       
  2423 		 7       PM1   PM2   PM3   PM4   PM5   PM6   PM7   PM8
       
  2424 		 8       PM9   PM10  PM11  PM12  PM13  PM14  PM15  PM16
       
  2425 
       
  2426 	Where:
       
  2427 	   B1-8   :  Baud rate
       
  2428        D1-2   :  data bits
       
  2429 	   S      :  Stop bits
       
  2430 	   P      :  Parity
       
  2431 	   PT1-2  :  Parity Type
       
  2432 	   FLC1-6 :  Flow ctrl type
       
  2433 	   XON1-8 :  Xon character
       
  2434 	   XOFF1-8:  Xoff character
       
  2435 	   PM1-16 :  Which values are to be set/accepted
       
  2436    
       
  2437 	See TS07.10 5.4.6.3.9 for more details
       
  2438 	@endverbatim
       
  2439 	**/
       
  2440 	{
       
  2441 	CRfcommMuxCtrlFrame* frm = 0;
       
  2442 	
       
  2443 	__ASSERT_DEBUG(aLen == KRPNCommandLength || aLen == KRPNRequestLength || 
       
  2444 				   aLen == KRPNResponseLength,	Panic(ERfcommInvalidRPNLength));
       
  2445 	LOG(_L("RFCOMM: Creating RPN frame"));
       
  2446 	frm=NewSignalFrame(aLen, aCommand, aSAP);
       
  2447 	if(!frm)
       
  2448 		return KErrNoMemory;
       
  2449 	
       
  2450 	frm->SetDLCI(aDLCI);	//	For use when matching DM responses to mux control command frames
       
  2451 	frm->SetCommandType(KRPNType, aCommand);
       
  2452 	frm->SetResponseNeeded(aCommand);
       
  2453 
       
  2454 	// Now the only parameter that's always present, the DLCI
       
  2455 	// Make sure the DLCI is only 6 bits long
       
  2456 	__ASSERT_DEBUG(aDLCI <= KMaxRfcommDLCI, Panic(ERfcommInvalidDLCI));
       
  2457 	aDLCI &= KMaxRfcommDLCI;
       
  2458 	frm->PutByte((aDLCI << 2) | 0x03); // Add E/A and C/R (both 1)
       
  2459 
       
  2460 	TUint8 valueOctet;
       
  2461 
       
  2462 	// If we're creating a negotiation request or a response of any kind,
       
  2463 	// fill in the rest of the value octets 
       
  2464 	if(aLen == KRPNCommandLength || aLen == KRPNResponseLength)
       
  2465 		{
       
  2466 		const TRfcommRemotePortParams& portParams = aRPNTransaction.iPortParams;
       
  2467 	
       
  2468 		// Second octet carries Baud Rate (AKA 'Bit Rate')
       
  2469 		TBps bitRate = EBps9600; //Just to stop the compiler warnings
       
  2470 		if(portParams.GetBitRate(bitRate)) // Sets bitRate if valid in portParams
       
  2471 			{
       
  2472 			valueOctet = 0;
       
  2473 			switch(bitRate)
       
  2474 				{
       
  2475 			// Magic numbers because enums are not the same 
       
  2476 			// values as the ones specified in the spec and 
       
  2477 			// adding even more enums would confuse matters
       
  2478 			case EBps2400:
       
  2479 				valueOctet = 0;
       
  2480 				break;
       
  2481 			case EBps4800:
       
  2482 				valueOctet = 1;
       
  2483 				break;
       
  2484 			case EBps7200:
       
  2485 			case EBps9600:
       
  2486 			case EBps19200:
       
  2487 			case EBps38400:
       
  2488 			case EBps57600:
       
  2489 			case EBps115200:
       
  2490 			case EBps230400:
       
  2491 				valueOctet = (bitRate - EBps7200) + 2;
       
  2492 				break;
       
  2493 			default:
       
  2494 				LOG(_L("RFCOMM:[rfcommmuxer.cpp] Invalid bitrate, ignoring"));
       
  2495 				__DEBUGGER(	);
       
  2496 				}
       
  2497 			}
       
  2498 		else
       
  2499 			{
       
  2500 			valueOctet = 0;
       
  2501 			}
       
  2502 		frm->PutByte(valueOctet);			
       
  2503 		
       
  2504 		// Third octet is compound. Each part is offset from 
       
  2505 		// the beginning of the octet.  
       
  2506 		//								Bit No. 76543210
       
  2507 		// Data Bits are stored at start:		000000XX
       
  2508 		const TUint8 KStopBitOffset		= 2; // 00000X00
       
  2509 		const TUint8 KParityBitOffset	= 3; // 0000X000
       
  2510 		const TUint8 KParityTypeOffset	= 4; // 00XX0000
       
  2511 		
       
  2512 		// Now it gets complicated - here we go...
       
  2513 		// Start with the 2 data bits
       
  2514 		TDataBits dataBits = EData5; //Just to stop the compiler warnings
       
  2515 		if(portParams.GetDataBits(dataBits))
       
  2516 			{
       
  2517 			switch (dataBits)
       
  2518 				{
       
  2519 				// Magic numbers because enums are not the same 
       
  2520 				// values as the ones specified in the spec and 
       
  2521 				// adding even more enums would confuse matters
       
  2522 				case EData5:	
       
  2523 					valueOctet = 0;
       
  2524 					break;
       
  2525 				case EData6:
       
  2526 					valueOctet = 2;
       
  2527 					break;
       
  2528 				case EData7:
       
  2529 					valueOctet = 1;
       
  2530 					break;
       
  2531 				case EData8:
       
  2532 					valueOctet = 3;
       
  2533 					break;
       
  2534 				default:
       
  2535 					__DEBUGGER();
       
  2536 					LOG(_L("TransmitRPN - Dodgy Data Bits. Assuming 0\n"));
       
  2537 					valueOctet = 0;
       
  2538 				}
       
  2539 			}
       
  2540 		else
       
  2541 			valueOctet = 0;
       
  2542 
       
  2543 		// Set the stop bit	if necessary
       
  2544 		// EStop1 corresponds to leaving the stop bit clear
       
  2545 		// EStop2 corresponds to setting the stop bit
       
  2546 		TStopBits stopBit = EStop1; //Just to stop the compiler warnings
       
  2547 		if(portParams.GetStopBit(stopBit))
       
  2548 			{
       
  2549 			if(stopBit == EStop2)
       
  2550 				valueOctet |=  (1 << KStopBitOffset);
       
  2551 			}
       
  2552 
       
  2553 		TParity parity = EParityNone; //Just to stop the compiler warnings
       
  2554 		if(portParams.GetParity(parity))
       
  2555 			{
       
  2556 			// Set the parity bit by default
       
  2557 			valueOctet |= (1 << KParityBitOffset);
       
  2558 			// Set Parity Type (and clear parity bit if necessary)
       
  2559 			switch(parity)
       
  2560 				{
       
  2561 				// Magic numbers because enums are not the same 
       
  2562 				// values as the ones specified in the spec and 
       
  2563 				// adding even more enums would confuse matters
       
  2564 				case EParityNone:
       
  2565 					// Clear the parity bit
       
  2566 					valueOctet &= ~(1 << KParityBitOffset); 
       
  2567 					break;
       
  2568 				case EParityOdd:
       
  2569 					// Do nothing, this parity type is stored as 0
       
  2570 					break;
       
  2571 				case EParityEven:
       
  2572 					valueOctet |= (2 << KParityTypeOffset);
       
  2573 					break;
       
  2574 				case EParityMark:
       
  2575 					valueOctet |= (1 << KParityTypeOffset); 
       
  2576 					break;
       
  2577 				case EParitySpace:
       
  2578 					valueOctet |= (3 << KParityTypeOffset); 
       
  2579 					break;
       
  2580 				}
       
  2581 			}
       
  2582 		// The reserved bits are already 0 so ignore them
       
  2583 		// Finally finished building Octet 3, now store it
       
  2584 		frm->PutByte(valueOctet);
       
  2585 
       
  2586 		// Octet 4 contains 6 flow control bits and 
       
  2587 		// 2 reserved bits (both zero)
       
  2588 		if(portParams.GetFlowCtrl(valueOctet))
       
  2589 			{
       
  2590 			// Make sure the Flow Control is only 6 bits
       
  2591 			if (valueOctet >> 6 != 0)
       
  2592 				{
       
  2593 				LOG(_L("Invalid Flow Control\n"));
       
  2594 				__DEBUGGER();
       
  2595 				delete frm;
       
  2596 				
       
  2597 				return KErrArgument;
       
  2598 				}
       
  2599 			frm->PutByte(valueOctet);
       
  2600 			}
       
  2601 		else
       
  2602 			{
       
  2603 			frm->PutByte(0);
       
  2604 			}
       
  2605 
       
  2606 
       
  2607 		// Octet 5 contains 8 XON bits
       
  2608 		if(portParams.GetXOnChar(valueOctet))
       
  2609 			{
       
  2610 			frm->PutByte(valueOctet);
       
  2611 			}
       
  2612 		else
       
  2613 			{
       
  2614 			frm->PutByte(0);
       
  2615 			}
       
  2616 		
       
  2617 		// Octet 6 contains 8 XOFF bits
       
  2618 		if(portParams.GetXOffChar(valueOctet))
       
  2619 			{
       
  2620 			frm->PutByte(valueOctet);
       
  2621 			}
       
  2622 		else
       
  2623 			{
       
  2624 			frm->PutByte(0);
       
  2625 			}
       
  2626 		
       
  2627 		// Octets 7 and 8 are the Parameter Mask
       
  2628 		// Lowest byte first...
       
  2629 		valueOctet = TUint8(aRPNTransaction.iParamMask & 0xff);
       
  2630 		frm->PutByte(valueOctet);
       
  2631 		// ...then the upper byte
       
  2632 		valueOctet = TUint8(aRPNTransaction.iParamMask >> 8);
       
  2633 		frm->PutByte(valueOctet);
       
  2634 		}
       
  2635 
       
  2636 	// Finished building frame, so send it	
       
  2637 	EnqueFrame(frm);
       
  2638 	
       
  2639 	return KErrNone;
       
  2640 	}
       
  2641 
       
  2642 
       
  2643 TInt CRfcommMuxer::TransmitPN(TUint8 aDLCI, TBool aCommand,
       
  2644 							  const TRfcommPortParams& aParams, CRfcommSAP* aSAP)
       
  2645 	/**
       
  2646 	   Format is:
       
  2647 	   @verbatim
       
  2648 	   Value Octet Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
       
  2649 	       1        D1    D2    D3    D4    D5    D6    0     0
       
  2650     	   2        I1    I2    I3    I4    CL1   CL2   CL3   CL4
       
  2651 	       3        P1    P2    P3    P4    P5    P6    0     0
       
  2652     	   4        T1    T2    T3    T4    T5    T6    T7    T8
       
  2653     	   5        N1    N2    N3    N4    N5    N6    N7    N8
       
  2654 	       6        N9    N10   N11   N12   N13   N14   N15   N16
       
  2655     	   7        NA1   NA2   NA3   NA4   NA5   NA6   NA7   NA8
       
  2656      	   8        K1    K2    K3    0     0     0     0     0
       
  2657 	   Where:
       
  2658 	     D1-6  : DLCI
       
  2659 		 I1-4  : frame type (must be zero)
       
  2660 		 CL1-4 : Convergence layer 
       
  2661 				 (if CBFC, set to 0x0f in request, 0x0e in response....
       
  2662 				  .....otherewise must be zero)
       
  2663 		 P1-6  : Priority
       
  2664 		 T1-8  : Acknowledgement timer T1 (must be zero)
       
  2665 		 N1-16 : Max frame size (default 127)
       
  2666 		 NA1-8 : Max retransmissions (must be zero)
       
  2667 		 K1-3  : Error recovery window 
       
  2668 				 (initial credit (0-7) for CBFC or set to 0 if fallback to FCon/off)
       
  2669 	  @endverbatim
       
  2670 	 **/
       
  2671 	{
       
  2672 	LOG3(_L("RFCOMM: Sending PN %S for dlci %d (MTU=%d)"), 
       
  2673 		(aCommand?&KCommandText:&KResponseText) , aDLCI, aParams.iMaxFrameSize);
       
  2674 	CRfcommMuxCtrlFrame* frm=NewSignalFrame(KRPNCommandLength, aCommand, aSAP);
       
  2675 
       
  2676 	if(!frm)
       
  2677 		return KErrNoMemory;
       
  2678 
       
  2679 	frm->SetDLCI(aDLCI);	//	For use when matching DM responses to mux control command frames
       
  2680 	frm->SetCommandType(KPNType, aCommand);
       
  2681 	frm->SetResponseNeeded(aCommand);
       
  2682 	// Now the 8 parameters
       
  2683 	__ASSERT_DEBUG(aDLCI <= KMaxRfcommDLCI, Panic(ERfcommInvalidDLCI));
       
  2684 	aDLCI &= KMaxRfcommDLCI;
       
  2685 	frm->PutByte(aDLCI);
       
  2686 	//TRY_CBFC ... NB used to do some negotiating here - but in current version all
       
  2687 	//				   such negotiation is performed in HandlePN
       
  2688 #ifdef NO_CBFC
       
  2689 	frm->PutByte(0x00);
       
  2690 #else
       
  2691 	frm->PutByte(iFlowStrategy->PNConvergenceLayer(aCommand));
       
  2692 #endif
       
  2693 	LOG2(_L("RFCOMM: CBFC Tried 0x%x, Type 0x%x"), iTriedCBFC, FlowType());
       
  2694 
       
  2695 	__ASSERT_DEBUG(aParams.iPriority <= KMaxRfcommPriority, Panic(ERfcommInvalidDLCI));
       
  2696 	TUint8 params = aParams.iPriority & KMaxRfcommPriority;
       
  2697 	frm->PutByte(params);
       
  2698 	frm->PutByte(0x00); // T bits
       
  2699 	frm->PutLittleEndian16(aParams.iMaxFrameSize);
       
  2700 	frm->PutByte(0x00); // NA bits
       
  2701 #ifdef NO_CBFC
       
  2702 	frm->PutByte(0x00);
       
  2703 #else
       
  2704 	frm->PutByte(aParams.iInitialCredit);
       
  2705 #endif
       
  2706 	EnqueFrame(frm);
       
  2707 	
       
  2708 	return KErrNone;
       
  2709 	}
       
  2710 
       
  2711 
       
  2712 TInt CRfcommMuxer::TransmitFCon(TBool aCommand, CRfcommSAP* aSAP)
       
  2713 	/**
       
  2714 	   Send a FCon command frame.
       
  2715 
       
  2716 	   If aCommand is True then this should be a command, else it is a
       
  2717 	   response.
       
  2718 	**/
       
  2719 	{
       
  2720 	LOG(_L("RFCOMM: Trying to send FCon"));
       
  2721 	if(!(iFlowStrategy->AllowFCOnOff(aCommand)))
       
  2722 		return KErrNotSupported; //Occurs if CBFC is on.
       
  2723 
       
  2724 	LOG1(_L("RFCOMM: Sending FCon %S"),aCommand?&KCommandText:&KResponseText);
       
  2725 	//FC
       
  2726 	CRfcommMuxCtrlFrame* frm=NewSignalFrame(KFConCommandLength, aCommand, aSAP);
       
  2727 	if(!frm)
       
  2728 		return KErrNoMemory;
       
  2729 
       
  2730 	frm->SetCommandType(KFConType, aCommand);
       
  2731 	frm->SetResponseNeeded(aCommand);
       
  2732 	EnqueFrame(frm);
       
  2733 	//
       
  2734 	return KErrNone;
       
  2735 	}
       
  2736 
       
  2737 TInt CRfcommMuxer::TransmitNSC(TBool aCommand, TUint8 aType)
       
  2738 	/**
       
  2739 	   Send a NSC command frame.
       
  2740 
       
  2741 	**/
       
  2742 	{
       
  2743 	LOG(_L("RFCOMM: Sending NSC"));
       
  2744 	
       
  2745 	CRfcommMuxCtrlFrame* frm=NewSignalFrame(KNSCCommandLength, EFalse);
       
  2746 	if(!frm)
       
  2747 		return KErrNoMemory;
       
  2748 
       
  2749 	frm->SetCommandType(KNSCType, EFalse);
       
  2750 	aCommand = (aCommand) ? 1 : 0;
       
  2751 	frm->PutByte(aType | (aCommand << 1));
       
  2752 	EnqueFrame(frm);
       
  2753 	
       
  2754 	return KErrNone;
       
  2755 	}
       
  2756 
       
  2757 
       
  2758 TInt CRfcommMuxer::TransmitFCoff(TBool aCommand, CRfcommSAP* aSAP)
       
  2759 	/**
       
  2760 	   Send a FCoff command frame.
       
  2761 
       
  2762 	   If aCommand is True then this should be a command, else it is a
       
  2763 	   response.
       
  2764 	**/
       
  2765 	{
       
  2766 	LOG(_L("RFCOMM: Trying to send FCoff"));
       
  2767 	if(!(iFlowStrategy->AllowFCOnOff(aCommand)))
       
  2768 		return KErrNotSupported; //Occurs if CBFC is on.
       
  2769 
       
  2770 	LOG1(_L("RFCOMM: Sending FCoff %S"),aCommand?&KCommandText:&KResponseText);
       
  2771 	//FC
       
  2772 	CRfcommMuxCtrlFrame* frm=NewSignalFrame(KFConCommandLength, aCommand, aSAP);
       
  2773 	if(!frm)
       
  2774 		return KErrNoMemory;
       
  2775 
       
  2776 	frm->SetCommandType(KFCoffType, aCommand);
       
  2777 	frm->SetResponseNeeded(aCommand);
       
  2778 	EnqueFrame(frm);
       
  2779 	//
       
  2780 	return KErrNone;
       
  2781 	}
       
  2782 
       
  2783 
       
  2784 TInt CRfcommMuxer::TransmitMSC(TUint8 aDLCI, TBool aCommand, TUint8 aSignals, CRfcommSAP* aSAP)
       
  2785 	/**
       
  2786 	   Send out a MSC signalling command (or response) which travels in a UIH frame
       
  2787 
       
  2788 	   Format is (TS07.10 5.4.6.3.7):
       
  2789 
       
  2790 	   | Command | Length | DLCI | Signals |
       
  2791 	**/
       
  2792 	{
       
  2793 	LOG3(_L("RFCOMM: SendMSC %S DLCI %d, Signals %x"),
       
  2794 		(aCommand?&KCommandText:&KResponseText), aDLCI, aSignals);
       
  2795 	
       
  2796 	CRfcommMuxCtrlFrame* frm=NewSignalFrame(KMSCCommandLength, aCommand, aSAP);
       
  2797 	if(!frm)
       
  2798 		return KErrNoMemory;
       
  2799 
       
  2800 	frm->SetDLCI(aDLCI);	//	For use when matching DM responses to mux control command frames
       
  2801 	frm->SetCommandType(KMSCType, aCommand);
       
  2802 	frm->SetResponseNeeded(aCommand);
       
  2803 	// DLCI
       
  2804 	frm->PutByte((aDLCI << 2) | 0x03); // dlci, 1, EA
       
  2805 	// Signals
       
  2806 	iFlowStrategy->OutgoingMSCReviseSignals(aCommand, aSignals); //FC-bit to zero if CBFC.
       
  2807 	frm->PutByte((aSignals << 1) | 0x01); // signals, EA
       
  2808 	EnqueFrame(frm);
       
  2809 	
       
  2810 	return KErrNone;
       
  2811 	}
       
  2812 
       
  2813 TInt CRfcommMuxer::TransmitTest(TBool aCommand, const TDesC8& aData, CRfcommSAP* aSAP)
       
  2814 	/**
       
  2815 	   Send out a Test signalling command
       
  2816 	**/
       
  2817 	{
       
  2818 	LOG1(_L("RFCOMM: Sending Test %S"),(aCommand?&KCommandText:&KResponseText));
       
  2819 	
       
  2820 	CRfcommMuxCtrlFrame* frm=NewSignalFrame(aData.Length(), aCommand, aSAP);
       
  2821 	if(!frm)
       
  2822 		return KErrNoMemory;
       
  2823 
       
  2824 	frm->SetCommandType(KTestType, aCommand);
       
  2825 	frm->SetResponseNeeded(aCommand);
       
  2826 	// Put the data in
       
  2827 	frm->PutData(aData);
       
  2828 	EnqueFrame(frm);
       
  2829 	
       
  2830 	return KErrNone;
       
  2831 	}
       
  2832 
       
  2833 TInt CRfcommMuxer::TransmitRLS(TBool aCommand, TUint8 aDLCI, TUint8 aStatus,
       
  2834 							   CRfcommSAP* aSAP)
       
  2835 	/**
       
  2836 	   Send out a RLS signalling command
       
  2837 	**/
       
  2838 	{
       
  2839 	CRfcommMuxCtrlFrame* frm=NewSignalFrame(KRLSCommandLength, aCommand, aSAP);
       
  2840 	if(!frm)
       
  2841 		return KErrNoMemory;
       
  2842 
       
  2843 	frm->SetDLCI(aDLCI);	//	For use when matching DM responses to mux control command frames
       
  2844 	frm->SetCommandType(KRLSType, aCommand);
       
  2845 	frm->SetResponseNeeded(aCommand);
       
  2846 	// Now the DLCI 
       
  2847 	frm->PutByte(aDLCI << 2 | 0x03);  // C/R & EA both 1
       
  2848 	// Now the status
       
  2849 	frm->PutByte(aStatus);
       
  2850 	EnqueFrame(frm);
       
  2851 	
       
  2852 	return KErrNone;
       
  2853 	}
       
  2854 
       
  2855 
       
  2856 TUint8 CRfcommMuxer::BuildAddr(TUint8 aDLCI, TBool aCommand)
       
  2857 	/**
       
  2858 	   Add C/R and EA bits to an existing DLCI to create an address field.
       
  2859 
       
  2860 	   Format of address is:
       
  2861 
       
  2862 	   EA | C/R | DLCI |
       
  2863 
       
  2864 	   where C/R depends on whether this is a command frame and what
       
  2865 	   the direction bit is set to.
       
  2866 	**/
       
  2867 
       
  2868 	{
       
  2869 	aDLCI<<=2; // Shift up for C/R and EA bits
       
  2870 	aDLCI |= 0x01; // EA is 1
       
  2871 	if(aCommand)
       
  2872 		{
       
  2873 		aDLCI |= iDirection << 1; // C/R is same as direction for commands
       
  2874 		}
       
  2875 	else
       
  2876 		{
       
  2877 		aDLCI |= (~iDirection & 1) << 1;  // Response has C/R =!Direction
       
  2878 		}
       
  2879 	return aDLCI;
       
  2880 	}
       
  2881 
       
  2882 CRfcommMuxCtrlFrame* CRfcommMuxer::NewSignalFrame(TInt aCommandLength, TBool aCommand, CRfcommSAP* aSAP)
       
  2883 /**
       
  2884 	Create a new UIH frame for a mux command
       
  2885 
       
  2886 	NB The command length excludes the Type octet and the Length octet(s)
       
  2887 **/
       
  2888 	{
       
  2889 	CRfcommMuxCtrlFrame* frm=NULL;
       
  2890 	TRAPD(err, frm=CRfcommMuxCtrlFrame::NewL(aCommandLength, *this, aSAP));
       
  2891 	if(!err)
       
  2892 		{
       
  2893 		// The C/R bit for the UIH frame is always 1 for the initiator
       
  2894 		// and 0 for the responder, which is the same as for commands.
       
  2895 		frm->SetAddress(BuildAddr(KMuxDLCI, ETrue));
       
  2896 		frm->SetControl(KUIHCtrlField);
       
  2897 		frm->SetResponseNeeded(aCommand);  // Commands need responses
       
  2898 		}
       
  2899 	return frm;	//	NB frm will be NULL if NewL failed.
       
  2900 	}
       
  2901 
       
  2902 CRfcommCtrlFrame* CRfcommMuxer::NewFrame(CRfcommSAP* aSAP)
       
  2903 	/**
       
  2904 	   Returns a ctrl frame (SABM, DISC, DM, UA)
       
  2905 	**/
       
  2906 	{
       
  2907 	return new CRfcommCtrlFrame(*this, aSAP);
       
  2908 	}
       
  2909 
       
  2910 CRfcommDataFrame* CRfcommMuxer::NewDataFrame(TUint8 aDLCI, TInt aLen, 
       
  2911 											 TUint8 aCredit, CRfcommSAP* aSAP)
       
  2912 	/**
       
  2913 	   Returns a new data (UIH) frame for the specified DLCI
       
  2914 
       
  2915 	   The C/R bit for the UIH frame is always 1 for the initiator and
       
  2916 	   0 for the responder, which is the same as for commands.
       
  2917 	**/
       
  2918 	{
       
  2919 	//	NB should be NULL if CRfcommDataFrame was not created
       
  2920 	return iFlowStrategy->NewDataFrame(*this, BuildAddr(aDLCI, ETrue), aLen, aCredit, aSAP);
       
  2921 	}
       
  2922 
       
  2923 TBool CRfcommMuxer::CheckFCS(TUint8 aFCS, TUint8 aCtrl)
       
  2924 	/**
       
  2925 	   Check the FCS on the incoming frame.
       
  2926 
       
  2927 	   FCS calculated over addr & ctrl for UIH, and addr, ctrl & len
       
  2928 	   for the others.
       
  2929 	**/
       
  2930 	{
       
  2931 	TUint8* data=&iNextPacket->Des()[0];
       
  2932 	TInt len;
       
  2933 	
       
  2934 	if(aCtrl == KUIHCtrlField)
       
  2935 		len=2;  // addr & ctrl fields
       
  2936 	else
       
  2937 		len=iCurrentHeaderLength;
       
  2938 
       
  2939 	return ::CheckFCS(data, len, aFCS);
       
  2940 	}
       
  2941 
       
  2942 CRfcommSAP* CRfcommMuxer::FindSAP(const TUint8 aDLCI)
       
  2943 	/**
       
  2944 	   Find the SAP that is on this channel.
       
  2945 
       
  2946 	   If no such sap exists, return 0
       
  2947 	**/
       
  2948 	{
       
  2949 	TDblQueIter<CRfcommSAP> iter(iSAPs);
       
  2950 	CRfcommSAP* sap;
       
  2951 
       
  2952 	while(iter)
       
  2953 		{
       
  2954 		sap=iter++;
       
  2955 		if(sap->DLCI() == aDLCI)
       
  2956 			return sap;
       
  2957 		}
       
  2958 
       
  2959 	iter=iBlockedSAPs;
       
  2960 	while(iter)
       
  2961 		{
       
  2962 		sap=iter++;
       
  2963 		if(sap->DLCI() == aDLCI)
       
  2964 			return sap;
       
  2965 		}
       
  2966 
       
  2967 	return 0;
       
  2968 	}
       
  2969 
       
  2970 CRfcommSAP* CRfcommMuxer::FindConnectedOrListeningSAP(const TUint8 aDLCI)
       
  2971 	/**
       
  2972 	Find a SAP that is on this channel, or get a listening SAP from the protocol.
       
  2973 
       
  2974 	If there is neither a SAP on this channel or a listening SAP then return NULL.
       
  2975 	**/
       
  2976 	{
       
  2977 	CRfcommSAP* mySAP=FindSAP(aDLCI);
       
  2978 	if(mySAP==NULL)
       
  2979 		{
       
  2980 		//	No SAP is currently in existance for this DLCI. 
       
  2981 		//	Find a listening SAP if possible.
       
  2982 		TBTSockAddr addr;
       
  2983 		addr.SetBTAddr(iRemoteAddr);
       
  2984 		addr.SetPort(aDLCI>>1);	//	i.e. convert from DLCI to server channel
       
  2985 		mySAP=iProtocol.FindIdleSAP(addr);
       
  2986 		}
       
  2987 
       
  2988 	return mySAP;
       
  2989 	}
       
  2990 
       
  2991 void CRfcommMuxer::EnqueFrame(CRfcommFrame* aFrm)
       
  2992 	/**
       
  2993 	   Add this frame to the outbound Q.
       
  2994 
       
  2995 	   Exactly where the frame is added depends on the type of frame,
       
  2996 	   frames where Priority==ETrue are added just behind any other 
       
  2997 	   priority frames in the queue, others are added right at the end.
       
  2998 	**/
       
  2999 	{
       
  3000 	//FC
       
  3001 	if(!aFrm->Priority())
       
  3002 		{
       
  3003 		//	Not a high priority frame. To the back of the entire queue!
       
  3004 		iOutboundQ.AddLast(*aFrm);
       
  3005 		}
       
  3006 	else
       
  3007 		{
       
  3008 		//	A priority frame. Jump to the back of the priority queue!
       
  3009 		
       
  3010 		//	First, we need to find the back of the priority queue...
       
  3011 		TDblQueIter<CRfcommFrame> iter(iOutboundQ);
       
  3012 		while(iter && (*iter).Priority())
       
  3013 			{
       
  3014 			iter++;
       
  3015 			}
       
  3016 
       
  3017 		if(iter)
       
  3018 			{
       
  3019 			//	We found a non-priority frame - jump into queue before this one
       
  3020 			aFrm->iLink.AddBefore(&(*iter).iLink);
       
  3021 			}
       
  3022 		else
       
  3023 			{
       
  3024 			//	We ran out of frames, so either entire Q is made up of priority
       
  3025 			//	frames, or the Q is empty. Either way, we can add to the end
       
  3026 			//	of the queue.
       
  3027 			iOutboundQ.AddLast(*aFrm);
       
  3028 			}
       
  3029 		}
       
  3030 	iOutboundQLength++;
       
  3031 	TryToSend();
       
  3032 	}
       
  3033 
       
  3034 void CRfcommMuxer::TryToSend()
       
  3035 	/**
       
  3036 		Just Q an async callback
       
  3037 	**/
       
  3038 	{
       
  3039 	iSendCallback->CallBack();
       
  3040 	}
       
  3041 		
       
  3042 TInt CRfcommMuxer::TryToSendCallbackStatic(TAny* aMux)
       
  3043 	{
       
  3044 	(static_cast<CRfcommMuxer*>(aMux))->TryToSendCallback();
       
  3045 	return EFalse;
       
  3046 	}
       
  3047 
       
  3048 #ifdef __FLOG_ACTIVE
       
  3049 void CRfcommMuxer::LogMuxCommand(CRfcommSAP* aSAP, CRfcommMuxer* /*aMux*/, TUint8 aCommand)
       
  3050 	{
       
  3051 	TUint8 signals;
       
  3052 
       
  3053 	switch(aCommand)
       
  3054 		{
       
  3055 	case KTestType:
       
  3056 			LOG(_L("TestCommand")); 
       
  3057 			break;
       
  3058 		case KPNType:
       
  3059 			LOG(_L("PN"));//
       
  3060 			break;
       
  3061 		case KRPNType:
       
  3062 			LOG(_L("RPN"));//
       
  3063 			break;
       
  3064 		case KFConType:
       
  3065 			//may need length byte value
       
  3066 			LOG(_L("FcOn"));//
       
  3067 			break;
       
  3068 		case KFCoffType:
       
  3069 			LOG(_L("FcOff"));//
       
  3070 			break;
       
  3071 		case KMSCType:
       
  3072 			if (aSAP)
       
  3073 				{
       
  3074 				signals = aSAP->Signals();//V.24 signals in MSC
       
  3075 				LOG1(_L("MSC %d"),signals);//
       
  3076 				}
       
  3077 			else
       
  3078 				{
       
  3079 				LOG(_L("RFCOMM: Unable to get signals for KMSCType command, unknown SAP"));
       
  3080 				}
       
  3081 			break;
       
  3082 		case KNSCType:
       
  3083 			LOG(_L("NSC"));//
       
  3084 			break;
       
  3085 		case KRLSType:
       
  3086 			LOG(_L("RLS"));//
       
  3087 		};
       
  3088 
       
  3089 	}
       
  3090 
       
  3091 void CRfcommMuxer::ExplainOutgoingFrame(CRfcommFrame* aFrm, CRfcommMuxer* aMux )
       
  3092 	{
       
  3093 #ifndef TCI
       
  3094 	//Show what type of frame we have sent and the various parts of the frame which are important.
       
  3095 
       
  3096 	TInt frametype = aFrm->Type(); //Is it a Ctrl Frame, Data Frame, CreditDataFrame or Mux Ctrl Frame ?
       
  3097 	TUint8 ctrlfield = aFrm->Ctrl();
       
  3098 	TUint8 ctrl = ctrlfield&~KPollFinalBitmask; //tells whether SABM, DISC, UA, DM
       
  3099 	TUint8 addressfield = aFrm->Address(); //Contains EA, CR, DLCI
       
  3100 //	TUint8 dlci = aMux->DecodeDLCI(addressfield); //extracts dlci
       
  3101 	TBool EA = addressfield & KEABitmask; //Is the EA bit set? 
       
  3102 	TBool CR = addressfield & KCRBitmask; //Is the CR bit set?
       
  3103 	TBool poll = ctrlfield & KPollFinalBitmask; //Is the p/f bit set?
       
  3104 	
       
  3105 	switch(frametype)
       
  3106 		{
       
  3107 		case KCtrlFrameType:
       
  3108 			{
       
  3109 			//CRfcommCtrlFrame* ctrlfrm=static_cast<CRfcommCtrlFrame*>(aFrm);
       
  3110 			//TUint16 ctrlframelength = ctrlfrm->DataLength();
       
  3111 			LOG(_L("Tx:"));
       
  3112 			
       
  3113 			if(ctrl==KSABMCtrlField)
       
  3114 				{
       
  3115 				LOG(_L("Tx: SABM"));
       
  3116 				}
       
  3117 			if(ctrl==KUACtrlField)
       
  3118 				{
       
  3119 				LOG(_L("Tx: UA"));
       
  3120 				}
       
  3121 			if(ctrl==KDMCtrlField)
       
  3122 				{
       
  3123 				LOG(_L("Tx: DM"));
       
  3124 				}
       
  3125 			if(ctrl==KDISCCtrlField)
       
  3126 				{
       
  3127 				LOG(_L("Tx: DISC"));
       
  3128 				}
       
  3129 			}
       
  3130 			break;
       
  3131 		case KDataFrameType: //CRfCommUIHFrame
       
  3132 			{
       
  3133 			CRfcommUIHFrame* uihfrm=static_cast<CRfcommUIHFrame*>(aFrm);
       
  3134 			TUint16 uihframelength = uihfrm->DataLength();
       
  3135 
       
  3136 			if(poll)
       
  3137 				LOG(_L("Tx: UIH credit data frame"));
       
  3138 			
       
  3139 			if (uihframelength<=127)
       
  3140 				{
       
  3141 				LOG(_L("Tx: UIH simple data frame"));
       
  3142 				}
       
  3143 			else
       
  3144 				{
       
  3145 				LOG(_L("Tx: UIH simple data frame"));
       
  3146 				}
       
  3147 			}
       
  3148 			break;
       
  3149 		case KCreditDataFrameType: //CRfcommCreditDataFrame
       
  3150 			{
       
  3151 			CRfcommCreditDataFrame* creditfrm=static_cast<CRfcommCreditDataFrame*>(aFrm);
       
  3152 			TUint8 credits = creditfrm->Credit();
       
  3153 			//BLOG Credits
       
  3154 			TUint16 length = creditfrm->DataLength();
       
  3155 			
       
  3156 			if (length<=127)
       
  3157 				{
       
  3158 				LOG1(_L("Tx: Short UIH credit data frame with %d credits"), credits);
       
  3159 				}
       
  3160 			else
       
  3161 				{
       
  3162 				LOG1(_L("Tx :Long UIH credit data frame with %d credits"), credits);
       
  3163 				}
       
  3164 			}
       
  3165 			break;
       
  3166 		case KMuxCtrlFrameType: //CRfcommMuxCtrlFrame containing muxer messages/commands
       
  3167 			{
       
  3168 			//#ifndef TCI
       
  3169 			CRfcommMuxCtrlFrame* muxfrm=static_cast<CRfcommMuxCtrlFrame*>(aFrm);
       
  3170 			TUint8 muxdlci = muxfrm->iDLCI;
       
  3171 			CRfcommSAP* sap = aMux->FindSAP(muxdlci); //Find the SAP that is on this dlci for aMux 
       
  3172 			TUint8 command = muxfrm->CommandType(); 
       
  3173 			if (sap)
       
  3174 				{
       
  3175 				LogMuxCommand(sap, aMux, command);
       
  3176 				}
       
  3177 			else
       
  3178 				{
       
  3179 				LOG1(_L("RFCOMM: Outgoing frame for unknown SAP: command = %d"),command);
       
  3180 				LogMuxCommand(NULL, aMux, command);
       
  3181 				}
       
  3182 			//#endif
       
  3183 			}
       
  3184 			break;
       
  3185 		default: //CRfcommDataFrame
       
  3186 			break;
       
  3187 		};
       
  3188 	LOG1(_L("         P/F bit = %d"), poll);
       
  3189 	LOG1(_L("         EA  bit = %d"), EA);
       
  3190 	LOG1(_L("         C/R bit = %d"), CR);
       
  3191 
       
  3192 	LOG1(_L("Frame of type %d"), frametype);
       
  3193 #endif
       
  3194 	}
       
  3195 #endif	//FLOG_ACTIVE
       
  3196 
       
  3197 void CRfcommMuxer::TryToSendCallback()
       
  3198 	/**
       
  3199 	   Attempt to send a frame off the bottom of the Q.
       
  3200 
       
  3201 		This is called back via an Async callback to break 
       
  3202 		"up to the top and down to the bottom from the RunL"	
       
  3203 
       
  3204 	   Currently assumes that a frame will always fit in an L2CAP
       
  3205 	   packet.
       
  3206 	**/
       
  3207 	{
       
  3208 	LOG1(_L("RFCOMM: Send Callback with Q len %d"), iOutboundQLength);
       
  3209 	CRfcommFrame* frm;
       
  3210 
       
  3211 	__ASSERT_DEBUG(!(iOutboundQLength !=0 && iOutboundQ.IsEmpty()),User::Panic(_L("Debug"),1));
       
  3212 
       
  3213 	while	(	!iOutboundQ.IsEmpty() && !L2CAPBlocked() && 
       
  3214 				((iOutboundQ.First()->Priority()) || ClearToSend())	)
       
  3215 		//	i.e. We have frames to send, L2CAP isn't blocked and we are EITHER clear to send
       
  3216 		//	OR we have priority frames to send.
       
  3217 		{
       
  3218 		LOG1(_L("RFCOMM: Sending @ Q len %d"), iOutboundQLength);
       
  3219 		frm=iOutboundQ.First();
       
  3220 		
       
  3221 		FTRACE(ExplainOutgoingFrame(frm, this));
       
  3222 #ifdef _DEBUG
       
  3223 		//FOR DEBUG PURPOSES ONLY
       
  3224 		if(frm->Address() != KMuxDLCI)
       
  3225 			{
       
  3226 			CRfcommSAP* sap = FindSAP(DecodeDLCI(frm->Address()));
       
  3227 			if(sap)
       
  3228 				{
       
  3229 				switch(frm->Ctrl())
       
  3230 					{
       
  3231 				case KUIHCtrlField:
       
  3232 				case KUIHCBFCCtrlField:
       
  3233 					if(frm->DataLength())
       
  3234 						{
       
  3235 						iDataFramesSent++;
       
  3236 						LOG1(_L("RFCOMM: Total data frames transmitted by mux (=> caused Tx decrement): %d"), iDataFramesSent);
       
  3237 						}
       
  3238 					break;
       
  3239 				default:
       
  3240 					break;
       
  3241 					}
       
  3242 				}
       
  3243 			}
       
  3244 #endif
       
  3245 
       
  3246 		// Datagram send, so 0 or length of packet returned
       
  3247 
       
  3248 		if(!iBoundSAP->Write(frm->Data(), 0))
       
  3249 			{
       
  3250 			LOG(_L("RFCOMM: L2CAP send failed, restoring frame"));
       
  3251 			L2CAPBlocked(ETrue);
       
  3252 			}
       
  3253 		else
       
  3254 			{
       
  3255 			// Managed to send this packet, so either move to responseQ or delete
       
  3256 			frm->iLink.Deque();
       
  3257 			if(frm->ResponseNeeded())
       
  3258 				{
       
  3259 				iResponseQ.AddLast(*frm);
       
  3260 				frm->QueResponseTimer();
       
  3261 				}
       
  3262 			else
       
  3263 				{
       
  3264 				delete frm;
       
  3265 				}
       
  3266 			iOutboundQLength--;
       
  3267 			}
       
  3268 		}
       
  3269 	
       
  3270 	// We may have made room for some new sap to send, so let them know
       
  3271 	SignalSAPsCanSend();
       
  3272 	
       
  3273 	// Equally, we may have sent all the remaining queued frames, and have no SAPs
       
  3274 	// left to service.
       
  3275 	CheckForIdle();
       
  3276 	}
       
  3277 
       
  3278 
       
  3279 void CRfcommMuxer::SignalSAPsCanSend()
       
  3280 	/**
       
  3281 	   We may be able to let some saps send, so start signalling them
       
  3282 	**/
       
  3283 	{
       
  3284 	CRfcommSAP* sap;
       
  3285 	TDblQueIter<CRfcommSAP> iter(iBlockedSAPs);
       
  3286 
       
  3287 	while(iter && !L2CAPBlocked() && ClearToSend())
       
  3288 		{
       
  3289 		sap = iter++;
       
  3290 		SetSendBlocked(*sap, EFalse);
       
  3291 		sap->CanSend();
       
  3292 		}
       
  3293 	}
       
  3294 
       
  3295 void CRfcommMuxer::CheckForIdle(TBool aClosing)
       
  3296 	/**
       
  3297 	   Check to see if we're still needed.  If not, Q a delayed delete.
       
  3298 	**/
       
  3299 	{
       
  3300 	if (aClosing)
       
  3301 		{
       
  3302 		// If we could be in the position where we have no SAPs then the next
       
  3303 		// time we set the idle timer we should use the closing value.
       
  3304 		iMuxIdleTimeout = KRfcommMuxIdleTimeoutClosing;
       
  3305 		}
       
  3306 		
       
  3307 	if(iOutboundQLength==0 && iSAPs.IsEmpty() && iBlockedSAPs.IsEmpty())
       
  3308 		{
       
  3309 		QueIdleTimer();
       
  3310 		}
       
  3311 	}
       
  3312 
       
  3313 void CRfcommMuxer::QueIdleTimer()
       
  3314 	/**
       
  3315 	   Queues the idle timer if necessary
       
  3316 	**/
       
  3317 	{
       
  3318 	if(!iIdleTimerQueued)
       
  3319 		{
       
  3320 		LOG2(_L("RFCOMM: Mux 0x%08x Q idle timer for %d microsecs"), this, iMuxIdleTimeout);
       
  3321 		iIdleTimerQueued=ETrue;
       
  3322 		BTSocketTimer::Queue(iMuxIdleTimeout, iIdleTimerEntry);
       
  3323 		}
       
  3324 	}
       
  3325 
       
  3326 void CRfcommMuxer::DequeIdleTimer()
       
  3327 	/**
       
  3328 	   Deques idle timer if necessary
       
  3329 	**/
       
  3330 	{
       
  3331 	if(iIdleTimerQueued)
       
  3332 		{
       
  3333 		LOG1(_L("RFCOMM: Mux 0x%08x deQ idle timer"), this);
       
  3334 		BTSocketTimer::Remove(iIdleTimerEntry);
       
  3335 		iIdleTimerQueued=EFalse;
       
  3336 		}
       
  3337 	}
       
  3338 
       
  3339 TInt CRfcommMuxer::IdleTimerExpired(TAny* aMux)
       
  3340 	/**
       
  3341 	   Static idle callback.
       
  3342 
       
  3343 	   This is entered after all our saps have gone away.
       
  3344 	   
       
  3345 	**/
       
  3346 	{
       
  3347  	LOG1(_L("RFCOMM: Mux %08x idle timer expired"), aMux);
       
  3348 	// Start the delete process
       
  3349 	CRfcommMuxer* mux = static_cast<CRfcommMuxer*>(aMux);
       
  3350 	mux->iIdleTimerQueued=EFalse;  // Obviously...
       
  3351 
       
  3352 	__ASSERT_DEBUG(mux->iSAPs.IsEmpty() && mux->iBlockedSAPs.IsEmpty(),
       
  3353 		           Panic(ERfcommIdleTimeoutWhenNotIdle));
       
  3354 	
       
  3355 	mux->iMuxChannel->Close();	//	May call back syncronously or asynchronously
       
  3356 								//	into MuxChannelClosed
       
  3357 	return FALSE;
       
  3358 	}
       
  3359 
       
  3360 void CRfcommMuxer::MuxChannelClosed()
       
  3361 	{
       
  3362 	// remove this muxer
       
  3363 	iProtocol.MuxDown(*this);	
       
  3364 	}
       
  3365 
       
  3366 void CRfcommMuxer::DeleteQueuedFrames()
       
  3367 	/**
       
  3368 		Delete all frames that are on either Q.
       
  3369 	**/	
       
  3370 	{
       
  3371 	TDblQueIter<CRfcommFrame> iter(iOutboundQ);
       
  3372 	CRfcommFrame* frm;
       
  3373 	
       
  3374 	while(iter)
       
  3375 		{
       
  3376 		frm=iter++;
       
  3377 		delete frm;
       
  3378 		}
       
  3379 	iOutboundQLength=0;
       
  3380 	
       
  3381 	iter=iResponseQ;
       
  3382 	while(iter)
       
  3383 		{
       
  3384 		frm=iter++;
       
  3385 		delete frm;
       
  3386 		}
       
  3387 	}
       
  3388