bluetooth/btstack/rfcomm/rfcommflow.cpp
changeset 0 29b1cd4cb562
child 13 16aa830c86c8
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <bluetooth/logger.h>
       
    17 #include <e32base.h>
       
    18 #include "rfcommutil.h"
       
    19 #include "rfcommmuxer.h"
       
    20 #include "rfcommflow.h"
       
    21 
       
    22 #ifdef __FLOG_ACTIVE
       
    23 _LIT8(KLogComponent, LOG_COMPONENT_RFCOMM);
       
    24 #endif
       
    25 
       
    26 /*************************************************************************/
       
    27 
       
    28 
       
    29 CRfcommFlowStrategyFactory::CRfcommFlowStrategyFactory()
       
    30 	{
       
    31 	LOG_FUNC
       
    32 //	iFlowStrategies.Reset();  // Null all the pointers -- not necessary as array is in CBase class.
       
    33 	}
       
    34 
       
    35 CRfcommFlowStrategyFactory::~CRfcommFlowStrategyFactory()
       
    36 	{
       
    37 	LOG_FUNC
       
    38 	// Destroy all the state objects
       
    39 	iFlowStrategies.DeleteAll();
       
    40 	}
       
    41 	
       
    42 CRfcommFlowStrategyFactory* CRfcommFlowStrategyFactory::NewL()
       
    43 	{
       
    44 	LOG_STATIC_FUNC
       
    45 	CRfcommFlowStrategyFactory* factory  = new (ELeave) CRfcommFlowStrategyFactory();
       
    46 	CleanupStack::PushL(factory);
       
    47 	// Create all the new states
       
    48 	factory->iFlowStrategies[EFlowInitial]  = new (ELeave) TRfcommFlowStrategyInitial(factory);
       
    49 	factory->iFlowStrategies[EFlowCreditBased] = new (ELeave) TRfcommFlowStrategyCreditBased(factory);
       
    50 	factory->iFlowStrategies[EFlowNonCreditBased] = new (ELeave) TRfcommFlowStrategyNonCreditBased(factory);
       
    51 	// etc...
       
    52 	CleanupStack::Pop();
       
    53 	return factory;
       
    54 	}
       
    55 
       
    56 TRfcommFlowStrategy& CRfcommFlowStrategyFactory::GetFlowStrategy(const TFlowStrategies aFlowStrategy) const
       
    57 	{
       
    58 	LOG_FUNC
       
    59 	__ASSERT_DEBUG(aFlowStrategy != EMaxFlowStrategy, Panic(ERfCommFlowStrategyOutOfBounds));
       
    60 	return *iFlowStrategies[aFlowStrategy];
       
    61 	}
       
    62 
       
    63 
       
    64 
       
    65 
       
    66 /*************************************************************************/
       
    67 
       
    68 
       
    69 
       
    70 TRfcommFlowStrategy::TRfcommFlowStrategy(CRfcommFlowStrategyFactory* aFactory)
       
    71 :iFactory(aFactory)
       
    72 	{
       
    73 	LOG_FUNC
       
    74 	//iFactory = aFactory;
       
    75 	}
       
    76 
       
    77 
       
    78 TRfcommFlowStrategy::~TRfcommFlowStrategy()
       
    79 	{
       
    80 	LOG_FUNC
       
    81 	}
       
    82 
       
    83 
       
    84 
       
    85 
       
    86 
       
    87 TRfcommFlowStrategyInitial::TRfcommFlowStrategyInitial(CRfcommFlowStrategyFactory* aFactory)
       
    88 :TRfcommFlowStrategy(aFactory) 
       
    89 	{
       
    90 	LOG_FUNC
       
    91 	}
       
    92 
       
    93 TRfcommFlowStrategyInitial::~TRfcommFlowStrategyInitial()
       
    94 	{
       
    95 	LOG_FUNC
       
    96 	}
       
    97 
       
    98 TInt TRfcommFlowStrategyInitial::DataBufferMultiple()
       
    99 	{
       
   100 	LOG_FUNC
       
   101 	return KRfcommSAPBufferMultiple;
       
   102 	};
       
   103 
       
   104 TUint16 TRfcommFlowStrategyInitial::UsableMTU(const CRfcommSAP& aSAP, TUint8 /*aCredit*/) const
       
   105 	/**
       
   106 	  Available frame space for data
       
   107 	**/
       
   108 	{
       
   109 	LOG_FUNC
       
   110 	__ASSERT_DEBUG(aSAP.NegotiatedMTU(), Panic(ERfcommBadCalculatedMTU));
       
   111 
       
   112 	return aSAP.NegotiatedMTU();
       
   113 	}
       
   114 
       
   115 TBool TRfcommFlowStrategyInitial::AllowWrite(CRfcommSAP& /*aSAP*/)
       
   116 	/**
       
   117 	  Ignore CBFC Credits
       
   118 	**/
       
   119 	{
       
   120 	LOG_FUNC
       
   121 	return ETrue;
       
   122 	}
       
   123 
       
   124 TBool TRfcommFlowStrategyInitial::AllowFCOnOff(TBool /*aCommand*/)
       
   125 	/**
       
   126 	  Always allow 'FC On/Off' commands (not be confused with FC bit in an MSC command!).
       
   127 	**/
       
   128 	{
       
   129 	LOG_FUNC
       
   130 	return ETrue;
       
   131 	}
       
   132 
       
   133 TInt TRfcommFlowStrategyInitial::PNConvergenceLayer(TBool aCommand)
       
   134 	/**
       
   135 	  We are negotiating so keep trying for CBFC.
       
   136 	**/
       
   137 	{
       
   138 	LOG_FUNC
       
   139 	return aCommand?KCBFCCommandFlag:KCBFCResponseFlag;
       
   140 	}
       
   141 
       
   142 TUint8 TRfcommFlowStrategyInitial::PNFinalOctet() // FIXME: Rename to InitialCredit()
       
   143 	/**
       
   144 	  We are negotiating so keep trying for CBFC.
       
   145 	**/
       
   146 	{
       
   147 	LOG_FUNC
       
   148 	return KInitialCredit;
       
   149 	}
       
   150 
       
   151 TUint8 TRfcommFlowStrategyInitial::WriteCredit(CRfcommSAP& /*aSAP*/)
       
   152 	/**
       
   153 	  Return number of CBFC credits to send in UIH frame.
       
   154 	**/
       
   155 	{
       
   156 	LOG_FUNC
       
   157 	return 0;
       
   158 	}
       
   159 
       
   160 
       
   161 void TRfcommFlowStrategyInitial::OutgoingMSCReviseSignals(TBool /*aCommand*/, TUint8& /*aSignals*/)
       
   162 	/**
       
   163 	  Only requires action for CBFC.
       
   164 	**/
       
   165 	{
       
   166 	LOG_FUNC
       
   167 	}
       
   168 
       
   169 void TRfcommFlowStrategyInitial::ReviseDonatedCredits(CRfcommSAP& /*aSAP*/, TUint8 /*aCredit*/)
       
   170 	/**
       
   171 	  Only requires action for CBFC.
       
   172 	**/
       
   173 	{
       
   174 	LOG_FUNC
       
   175 	}
       
   176 
       
   177 void TRfcommFlowStrategyInitial::ReviseTransmittedCredits(CRfcommSAP& /*aSAP*/)
       
   178 	{
       
   179 	LOG_FUNC
       
   180 	/**
       
   181 	  Only requires action for CBFC.
       
   182 	**/
       
   183 	}
       
   184 
       
   185 CRfcommDataFrame* TRfcommFlowStrategyInitial::NewDataFrame(CRfcommMuxer& aMuxer, 
       
   186 													 TUint8 aAddr, 
       
   187 												     TInt aLen, 
       
   188 #ifdef _DEBUG
       
   189 												     TUint8 aCredit,
       
   190 #else
       
   191 												     TUint8 /*aCredit*/,
       
   192 #endif
       
   193 
       
   194 												     CRfcommSAP* aSAP)
       
   195 	/**
       
   196 	   Returns a new data (UIH) frame for the specified DLCI
       
   197 
       
   198 	   The C/R bit for the UIH frame is always 1 for the initiator and
       
   199 	   0 for the responder, which is the same as for commands.
       
   200 	**/
       
   201 	{
       
   202 	LOG_FUNC
       
   203 	__ASSERT_DEBUG(!aCredit, Panic(ERfcommUnexpectedCBFCCredit));
       
   204 	CRfcommDataFrame* frm=NULL;
       
   205 	TRAPD(err, frm=CRfcommDataFrame::NewL(aLen, aMuxer, aSAP));
       
   206 	if(!err)
       
   207 		{
       
   208 		frm->SetAddress(aAddr);
       
   209 		frm->SetControl(KUIHCtrlField);
       
   210 		}
       
   211 	return frm;	//	NB should be NULL if CRfcommDataFrame was not created
       
   212 	}
       
   213 
       
   214 TBool TRfcommFlowStrategyInitial::CanProcessNewData(const TBool aAllowProcessNewData) const
       
   215 	/**
       
   216 	  If a SAP's buffer becomes too full, then that SAP will cause the muxer
       
   217 	  to block any further intake of data. 'aSAPNoFreeSpaceMask' points to the
       
   218 	  relevant muxer flag.
       
   219 	**/
       
   220 	{
       
   221 	LOG_FUNC
       
   222 	return aAllowProcessNewData;
       
   223 	}
       
   224 
       
   225 void TRfcommFlowStrategyInitial::DecodeLength(TBool /*aCBFC*/, 
       
   226 										 	  TDesC8& /*aPacket*/, 
       
   227 											  TInt& /*aCreditBuffer*/, 
       
   228 											  TInt& /*aHeaderLengthBuffer*/)
       
   229 	/**
       
   230 	  Do nothing - not CBFC.
       
   231 	**/
       
   232 	{
       
   233 	LOG_FUNC
       
   234 	}
       
   235 
       
   236 TBool TRfcommFlowStrategyInitial::ProcessDataFrameReviseCredits(CRfcommSAP& /*aSAP*/, 
       
   237 													   TBool /*aPoll*/,
       
   238 													   TUint8 /*aCredit*/)
       
   239 	/**
       
   240 	  Not CBFC - return false => do nothing.
       
   241 	**/
       
   242 	{
       
   243 	LOG_FUNC
       
   244 	return EFalse;
       
   245 	}
       
   246 
       
   247 TBool TRfcommFlowStrategyInitial::MSC(CRfcommSAP& aSAP, TUint8 aSignals)
       
   248 	/**
       
   249 	  Respond to flow control aspects of an MSC signal.
       
   250 	**/
       
   251 	{
       
   252 	LOG_FUNC
       
   253 	// Set CTS. We're clear to send if flow control is off so this 
       
   254 	// is the inverse of the Flow Control bit
       
   255 	aSAP.CTS(!(aSignals & KModemSignalFC));
       
   256 	if(aSAP.CTS())
       
   257 		{
       
   258 		// Unblock ESOCK to try again (which might block again!)
       
   259 		return ETrue;
       
   260 		}
       
   261 	return EFalse;
       
   262 	}
       
   263 
       
   264 void TRfcommFlowStrategyInitial::UpdateRxFlowControlState(CRfcommSAP& aSAP)
       
   265 	/**
       
   266 		Do non-CBFC flow control.
       
   267 	**/
       
   268 	{
       
   269 	LOG_FUNC
       
   270 	if(aSAP.DataBuffer().Count() + aSAP.Mux()->GetMaxDataSize() <=
       
   271 	   aSAP.DataBuffer().Length())
       
   272 		{
       
   273 		// Let the mux know we can take more data
       
   274 		//FC
       
   275 		aSAP.Mux()->SetCanHandleData(aSAP, ETrue);
       
   276 		}
       
   277 
       
   278 	if(aSAP.DataBuffer().Count() <= aSAP.LowTideMark())
       
   279 		{
       
   280 		if(!aSAP.CTR())
       
   281 			{
       
   282 			// We should send a flow on since we've sent an off
       
   283 			//FC
       
   284 			TUint8 signals=aSAP.Signals();
       
   285 			signals &= (~KModemSignalFC);
       
   286 			TInt result=aSAP.Mux()->SendMSC(aSAP, signals);
       
   287 			if(result == KErrNone)
       
   288 				{
       
   289 				// Update state if we sent it, otherwise don't
       
   290 				aSAP.SetSignals(signals);
       
   291 				aSAP.CTR(ETrue);
       
   292 				}
       
   293 			//
       
   294 			}
       
   295 		}
       
   296 	}
       
   297 
       
   298 TBool TRfcommFlowStrategyInitial::NewDataReviseCredits(CRfcommSAP& /*aSAP*/, const TDesC8& /*aData*/)
       
   299 	/**
       
   300 		Do nothing - SAPWise (CBFC) only.
       
   301 	**/
       
   302 	{
       
   303 	LOG_FUNC
       
   304 	return ETrue;
       
   305 	}
       
   306 
       
   307 void TRfcommFlowStrategyInitial::NewData(CRfcommSAP& aSAP)
       
   308 	/**
       
   309 		Deal with flow control when new data is coming in and CBFC is not on.
       
   310 	**/
       
   311 	{
       
   312 	LOG_FUNC
       
   313 	if(aSAP.DataBuffer().Count() + aSAP.Mux()->GetMaxDataSize() >=
       
   314 	   aSAP.DataBuffer().Length())
       
   315 		/**
       
   316 			N.B. CircularBuffers: Length() is MaxLength() and Count() is Length()!
       
   317 		**/
       
   318 		{
       
   319 		//Tell the mux we canna take any more, capt'n
       
   320 		aSAP.Mux()->SetCanHandleData(aSAP, EFalse);
       
   321 		}
       
   322 		
       
   323 	if(aSAP.DataBuffer().Count() >= aSAP.HighTideMark())
       
   324 		{
       
   325 		// Now try to send a flow off, if we haven't already
       
   326 		if(aSAP.CTR())
       
   327 			{
       
   328 			//FC
       
   329 			TUint8 signals=aSAP.Signals();
       
   330 			signals |= KModemSignalFC;
       
   331 			TInt result=aSAP.Mux()->SendMSC(aSAP, signals);
       
   332 			if(result == KErrNone)
       
   333 				{
       
   334 				// we sent it, so update state
       
   335 				aSAP.SetSignals(signals);
       
   336 				aSAP.CTR(EFalse);
       
   337 				}
       
   338 			//
       
   339 			}
       
   340 		}
       
   341 	return;
       
   342 	}
       
   343 
       
   344 CRfcommFlowStrategyFactory::TFlowStrategies TRfcommFlowStrategyInitial::FlowType()
       
   345 	{
       
   346 	LOG_FUNC
       
   347 	return CRfcommFlowStrategyFactory::EFlowInitial;
       
   348 	}
       
   349 
       
   350 
       
   351 TRfcommFlowStrategyCreditBased::TRfcommFlowStrategyCreditBased(CRfcommFlowStrategyFactory* aFactory)
       
   352 :TRfcommFlowStrategyInitial(aFactory) 
       
   353 	{
       
   354 	LOG_FUNC
       
   355 	}
       
   356 
       
   357 TRfcommFlowStrategyCreditBased::~TRfcommFlowStrategyCreditBased()
       
   358 	{
       
   359 	LOG_FUNC
       
   360 	}
       
   361 
       
   362 
       
   363 TInt TRfcommFlowStrategyCreditBased::DataBufferMultiple()
       
   364 	{
       
   365 	LOG_FUNC
       
   366 	return KRfcommSAPCBFCBufferMultiple;
       
   367 	};
       
   368 
       
   369 TUint16 TRfcommFlowStrategyCreditBased::UsableMTU(const CRfcommSAP& aSAP, TUint8 aCredit) const
       
   370 	/**
       
   371 	  Available frame space for data
       
   372 	**/
       
   373 	{
       
   374 	LOG_FUNC
       
   375 	__ASSERT_DEBUG(aSAP.NegotiatedMTU(), Panic(ERfcommBadCalculatedMTU));
       
   376 
       
   377 	//Allow for possible credit in header.
       
   378 	return (STATIC_CAST(TUint16, (aSAP.NegotiatedMTU() - (aCredit?1:0))));
       
   379 	}
       
   380 
       
   381 TBool TRfcommFlowStrategyCreditBased::AllowWrite(CRfcommSAP& aSAP)
       
   382 	/**
       
   383 	**/
       
   384 	{
       
   385 	LOG_FUNC
       
   386 	return aSAP.LocalCredit();
       
   387 	}
       
   388 
       
   389 TBool TRfcommFlowStrategyCreditBased::AllowFCOnOff(TBool aCommand)
       
   390 	/**
       
   391 	  Allow responses only. Do not transmit an 'FC On/Off' command.
       
   392 	  (not be confused with FC bit in an MSC command!)
       
   393 	**/
       
   394 	{
       
   395 	LOG_FUNC
       
   396 	return !aCommand; //N.B. Reverse logic - if command then return 'EFalse'
       
   397 	}
       
   398 
       
   399 TUint8 TRfcommFlowStrategyCreditBased::WriteCredit(CRfcommSAP& aSAP)
       
   400 	/**
       
   401 	  Return number of CBFC credits to send in UIH frame
       
   402 	**/
       
   403 	{
       
   404 	LOG_FUNC
       
   405 	return aSAP.FreeCredit();
       
   406 	}
       
   407 
       
   408 void TRfcommFlowStrategyCreditBased::OutgoingMSCReviseSignals(TBool aCommand, TUint8& aSignals)
       
   409 	/**
       
   410 	  There is a bit that when zero => CTS should be set to true. 
       
   411 	  For CBFC this bit must always be zero if we are sending a command. 
       
   412 	  Thus we are masking that part of an MSC command which tells the remote 
       
   413 	  to switch its CTS off (and so stop sending). 
       
   414 	  Required by SPEC.
       
   415 	**/
       
   416 	{
       
   417 	LOG_FUNC
       
   418 	if(aCommand)
       
   419 		aSignals &= (~KModemSignalFC);
       
   420 	}
       
   421 
       
   422 void TRfcommFlowStrategyCreditBased::ReviseDonatedCredits(CRfcommSAP& aSAP, TUint8 aCredit)
       
   423 	/**
       
   424 	  Revise proxy credit (our knowledge of remote credit) upwards by 'aCredit'.
       
   425 	**/
       
   426 	{
       
   427 	LOG_FUNC
       
   428 	//credit change
       
   429 	//Increase proxy credit by 'aCredit'.
       
   430 	aSAP.ProxyForRemoteCreditAddCredit(aCredit);
       
   431 	}
       
   432 
       
   433 void TRfcommFlowStrategyCreditBased::ReviseTransmittedCredits(CRfcommSAP& aSAP)
       
   434 	/**
       
   435 	  Revise our own credits downward by one.
       
   436 	  Revise proxy credit (our knowledge of remote credit) upwards by 'aCredit'.
       
   437 	**/
       
   438 	{
       
   439 	LOG_FUNC
       
   440 	//Decrement allowed transmission credits.
       
   441 	aSAP.LocalCreditDecrement();
       
   442 	}
       
   443 
       
   444 CRfcommDataFrame* TRfcommFlowStrategyCreditBased::NewDataFrame(CRfcommMuxer& aMuxer, 
       
   445 												   TUint8 aAddr, 
       
   446 												   TInt aLen, 
       
   447 												   TUint8 aCredit,
       
   448 												   CRfcommSAP* aSAP)
       
   449 	/**
       
   450 	   Returns a new data (UIH) frame for the specified DLCI
       
   451 
       
   452 	   The C/R bit for the UIH frame is always 1 for the initiator and
       
   453 	   0 for the responder, which is the same as for commands.
       
   454 	**/
       
   455 	{
       
   456 	LOG_FUNC
       
   457 	CRfcommDataFrame* frm=NULL;
       
   458 	TInt err = 0;
       
   459 	if(aCredit)
       
   460 		{
       
   461 		TRAP(err, frm=CRfcommCreditDataFrame::NewL(aLen, aMuxer, aSAP));
       
   462 		if(!err)
       
   463 			{
       
   464 			frm->SetAddress(aAddr);
       
   465 			frm->SetControl(KUIHCBFCCtrlField); //FIXME - redone later
       
   466 			((CRfcommCreditDataFrame*)frm)->SetCredit(aCredit);
       
   467 			}
       
   468 		}
       
   469 	else
       
   470 		{
       
   471 		TRAP(err, frm=CRfcommDataFrame::NewL(aLen, aMuxer, aSAP));
       
   472 		if(!err)
       
   473 			{
       
   474 			frm->SetAddress(aAddr);
       
   475 			frm->SetControl(KUIHCtrlField); //FIXME - redone later ... Poll bit always 0 for UIH
       
   476 			}
       
   477 		}
       
   478 	return frm;	//	NB should be NULL if CRfcommDataFrame was not created
       
   479 	}
       
   480 
       
   481 TBool TRfcommFlowStrategyCreditBased::CanProcessNewData(const TBool /*aAllowProcessNewData*/) const
       
   482 	/**
       
   483 	  CBFC is on (=>SAP wise flow control). This function is for MUX wide 
       
   484 	  flow control, and so should ignore all flags and never block here.
       
   485 	**/
       
   486 	{
       
   487 	LOG_FUNC
       
   488 	return ETrue;
       
   489 	}
       
   490 
       
   491 void TRfcommFlowStrategyCreditBased::DecodeLength(TBool aCBFC, 
       
   492 											      TDesC8& aPacket, 
       
   493 											      TInt& aCreditBuffer, 
       
   494 											      TInt& aHeaderLengthBuffer)
       
   495 	/**
       
   496 		Provides the credit buffer with the sent credit, and revises the
       
   497 		header length buffer to take credit byte into account.
       
   498 	**/
       
   499 	{
       
   500 	LOG_FUNC
       
   501 	TInt cIndex = ((aPacket)[2] & 1)?3:4;
       
   502 	if (aCBFC)
       
   503 		{
       
   504 		aCreditBuffer = aPacket[cIndex];
       
   505 		aHeaderLengthBuffer++;	// data is 1 byte smaller
       
   506 		LOG1(_L("RFCOMM: Incoming packet: value in credit field is %d"), aCreditBuffer);
       
   507 		}
       
   508 	else
       
   509 		{
       
   510 		LOG(_L("RFCOMM: No credit field in incoming packet"));
       
   511 		}
       
   512 	}
       
   513 
       
   514 TBool TRfcommFlowStrategyCreditBased::ProcessDataFrameReviseCredits(CRfcommSAP& aSAP, 
       
   515 													   TBool aPoll,
       
   516 													   TUint8 aCredit)
       
   517 	/**
       
   518 	   Add 'aCredit' (discovered in incoming data frame)to our credit.
       
   519 	   If as a result we have credits when non had previously existed, 
       
   520 	   return true to unblock SAP.
       
   521 	**/
       
   522 	//credit change
       
   523 	{
       
   524 	LOG_FUNC
       
   525 	LOG(_L("CRfcommFlowSAPWise::ProcessDataFrameReviseCredits"));
       
   526 	if (aPoll)
       
   527 		{
       
   528 		TBool isUnblock = (!(aSAP.LocalCredit()) && aCredit)?ETrue:EFalse;
       
   529 		aSAP.LocalCreditAddCredit(aCredit);
       
   530 		if (isUnblock)
       
   531 			{
       
   532 			LOG(_L("RFCOMM: Transmit credit was zero."));
       
   533 			if (aSAP.SendBlocked() & CRfcommSAP::EBlockedByMux)
       
   534 				{
       
   535 				return ETrue;
       
   536 				}
       
   537 			}
       
   538 		}
       
   539 	else
       
   540 		{
       
   541 		LOG(_L("RFCOMM: Data with no Tx Credit"));
       
   542 		}
       
   543 	return EFalse;
       
   544 	}
       
   545 
       
   546 TBool TRfcommFlowStrategyCreditBased::MSC(CRfcommSAP& aSAP, TUint8 /*aSignals*/)
       
   547 	/**
       
   548 	  "Clear To Send" must be set to true. Flow control is handled
       
   549 	  only by credits. See "AllowWrite()".
       
   550 	**/
       
   551 	{
       
   552 	LOG_FUNC
       
   553 	aSAP.CTS(ETrue);
       
   554 	return ETrue;
       
   555 	}
       
   556 
       
   557 void TRfcommFlowStrategyCreditBased::UpdateRxFlowControlState(CRfcommSAP& aSAP)
       
   558 	/**
       
   559 	  Donate credits if possible when data is read off SAPs ring buffer.
       
   560 	  Note: Function was called Read() originally, but actually is independent
       
   561 	  of anything to do with reading.
       
   562 	**/
       
   563 	{
       
   564 	LOG_FUNC
       
   565 	if(aSAP.ProxyForRemoteCredit() <= KRfcommCreditsLowWaterMark)
       
   566 		{
       
   567 		TUint8 spareCredits = aSAP.FreeCredit();
       
   568 		if (spareCredits && spareCredits>=aSAP.ProxyForRemoteCredit())
       
   569 			{// We've got a worth while no. of credits to forward. Do a donation.
       
   570 			aSAP.Mux()->Donate(aSAP, spareCredits);	// send an empty frame with credits
       
   571 			}
       
   572 		}
       
   573 	LOG2(_L("RFCOMM: After: RxCr %d, ReUsed (or Free) %d"), aSAP.ProxyForRemoteCredit(), aSAP.FreeCreditCalculation());
       
   574 	}
       
   575 
       
   576 TBool TRfcommFlowStrategyCreditBased::NewDataReviseCredits(CRfcommSAP& aSAP, const TDesC8& aData)
       
   577 	/**
       
   578 		Revise proxy credit downwards by one if a frame has arrived containing 
       
   579 		new data.
       
   580 	**/
       
   581 	//credit change
       
   582 	{
       
   583 	LOG_FUNC
       
   584 	if (aData.Length() > 0)
       
   585 		{
       
   586 		if (aSAP.ProxyForRemoteCredit() == 0)
       
   587 			{
       
   588 			// got to disconnect cos they're ignoring our credits
       
   589 			LOG(_L("RFCOMM: Data received with 0 receive credit"));
       
   590 			return EFalse;
       
   591 			}
       
   592 		else
       
   593 			{
       
   594 			// update remote transmit credit proxy
       
   595 			aSAP.ProxyForRemoteCreditDecrement();
       
   596 			}
       
   597 		}
       
   598 	return ETrue;
       
   599 	}
       
   600 
       
   601 void TRfcommFlowStrategyCreditBased::NewData(CRfcommSAP& aSAP)
       
   602 	/**
       
   603 		If other side have run out of credits, check that we really
       
   604 		don't have any to send them. This should rarely happen, as
       
   605 		NotifyNewData tries to forward credits before they run out.
       
   606 	**/
       
   607 	{
       
   608 	LOG_FUNC
       
   609 	if (aSAP.ProxyForRemoteCredit() == 0)
       
   610 		{// they have run out! See if we have any credits
       
   611 		TUint8 spareCredits = aSAP.FreeCredit();
       
   612 		if(spareCredits)
       
   613 			{// got some credits! Send them.
       
   614 			aSAP.Mux()->Donate(aSAP, spareCredits);	// an empty frame with credits
       
   615 			}
       
   616 		}
       
   617 	return;
       
   618 	}
       
   619 
       
   620 CRfcommFlowStrategyFactory::TFlowStrategies TRfcommFlowStrategyCreditBased::FlowType()
       
   621 	{
       
   622 	LOG_FUNC
       
   623 	return CRfcommFlowStrategyFactory::EFlowCreditBased;
       
   624 	}
       
   625 
       
   626 
       
   627 
       
   628 
       
   629 
       
   630 
       
   631 TRfcommFlowStrategyNonCreditBased::TRfcommFlowStrategyNonCreditBased(CRfcommFlowStrategyFactory* aFactory)
       
   632 :TRfcommFlowStrategyInitial(aFactory) 
       
   633 	{
       
   634 	LOG_FUNC
       
   635 	}
       
   636 
       
   637 TRfcommFlowStrategyNonCreditBased::~TRfcommFlowStrategyNonCreditBased()
       
   638 	{
       
   639 	LOG_FUNC
       
   640 	}
       
   641 
       
   642 
       
   643 
       
   644 TInt TRfcommFlowStrategyNonCreditBased::PNConvergenceLayer(TBool /*aCommand*/)
       
   645 	/**
       
   646 	  Always allow 'FC On/Off'.
       
   647 	**/
       
   648 	{
       
   649 	LOG_FUNC
       
   650 	return 0x00;
       
   651 	}
       
   652 
       
   653 TUint8 TRfcommFlowStrategyNonCreditBased::PNFinalOctet()
       
   654 	/**
       
   655 	  Return 0.
       
   656 	**/
       
   657 	{
       
   658 	LOG_FUNC
       
   659 	return 0x00;
       
   660 	}
       
   661 
       
   662 
       
   663 CRfcommFlowStrategyFactory::TFlowStrategies TRfcommFlowStrategyNonCreditBased::FlowType()
       
   664 	{
       
   665 	LOG_FUNC
       
   666 	return CRfcommFlowStrategyFactory::EFlowNonCreditBased;
       
   667 	}
       
   668