bluetooth/btstack/rfcomm/rfcommstates.cpp
changeset 0 29b1cd4cb562
child 8 2b6718f05bdb
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 1997-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 <bt_sock.h>
       
    18 #include "rfcommstates.h"
       
    19 #include "rfcomm.h"
       
    20 #include "rfcommmuxer.h"
       
    21 #include "rfcommflow.h"
       
    22 #include "rfcommconsts.h"
       
    23 #include "AsyncErrorKicker.h"
       
    24 
       
    25 #ifdef __FLOG_ACTIVE
       
    26 _LIT8(KLogComponent, LOG_COMPONENT_RFCOMM);
       
    27 #endif
       
    28 
       
    29 // Together, these classes and the SAP implement the State pattern
       
    30 // (GOF).  The states themselves are implemented using the Flyweight
       
    31 // pattern.  Each state is a Flyweight object, and CRfcommStateFactory
       
    32 // is manager of these objects.  As a result of being a flyweight, no
       
    33 // state object may have state that can't be shared between all
       
    34 // possible users of the state (ie no per-SAP state)
       
    35 
       
    36 
       
    37 CRfcommStateFactory* CRfcommStateFactory::NewL()
       
    38 	/**
       
    39 	   Create all the state singletons.
       
    40 	**/
       
    41 	{
       
    42 	CRfcommStateFactory* factory= new (ELeave) CRfcommStateFactory();
       
    43 	CleanupStack::PushL(factory);
       
    44 	// Create all the new states
       
    45 	factory->ConstructL();
       
    46 	CleanupStack::Pop();
       
    47 	return factory;
       
    48 	}
       
    49 
       
    50 void CRfcommStateFactory::ConstructL()
       
    51 	{
       
    52 	iStates[EError]  = new (ELeave) TRfcommStateError(*this);
       
    53 	iStates[EClosed] = new (ELeave) TRfcommStateClosed(*this);
       
    54 	iStates[EWaitForMux]= new (ELeave) TRfcommStateWaitForMux(*this);
       
    55 	iStates[EWaitForPNResp]= new (ELeave) TRfcommStateWaitForPNResp(*this);
       
    56 	iStates[EWaitForUA]= new (ELeave) TRfcommStateWaitForUA(*this);
       
    57 	iStates[EOpen]      = new (ELeave) TRfcommStateOpen(*this);
       
    58 	iStates[EDisconnect]      = new (ELeave) TRfcommStateDisconnect(*this);
       
    59 	iStates[EListening] = new (ELeave) TRfcommStateListening(*this);
       
    60 	iStates[EWaitForSABM] = new (ELeave) TRfcommStateWaitForSABM(*this);
       
    61 	iStates[EWaitForIncomingSecurityCheck] = new (ELeave) TRfcommStateIncomingSecurityCheck(*this);
       
    62 	iStates[EWaitForOutgoingSecurityCheck] = new (ELeave) TRfcommStateOutgoingSecurityCheck(*this);
       
    63 	iStates[EWaitForStart] = new (ELeave) TRfcommStateWaitForStart(*this);
       
    64 	iStates[ECloseOnStart] = new (ELeave) TRfcommStateCloseOnStart(*this);
       
    65 	iStates[EDisconnecting] = new (ELeave) TRfcommStateDisconnecting(*this);
       
    66 	// etc...
       
    67 	}
       
    68 
       
    69 TInt CRfcommStateFactory::StateIndex(const TRfcommState* aState) const
       
    70 	{
       
    71 	TInt state;
       
    72 	for (state = 0; state < ERfcommMaxState; state++)
       
    73 		{
       
    74 		if (iStates[state] == aState)
       
    75 			{
       
    76 			return state;
       
    77 			}
       
    78 		}
       
    79 	
       
    80 	return KUnknownState;
       
    81 	}
       
    82 
       
    83 /*
       
    84 
       
    85 TRfcommState base class implementation
       
    86 
       
    87 */
       
    88 
       
    89 TInt TRfcommState::SignalError(CRfcommSAP& aSAP, TInt aErr, MSocketNotify::TOperationBitmasks aType)
       
    90 	/**
       
    91 	   Signal an error, with appropriate types to tell socket what's
       
    92 	   been affected.
       
    93 	**/
       
    94 	{
       
    95 	if (aSAP.iSocket)
       
    96 		{
       
    97 		aSAP.iSocket->Error(aErr, aType);
       
    98 		}
       
    99 
       
   100 	if(aType & MSocketNotify::EErrorFatal)
       
   101 		{
       
   102 		aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EUndoOverridePark, aSAP.iRemoteDev);
       
   103 		ChangeState(aSAP, CRfcommStateFactory::EError);
       
   104 		}
       
   105 	return aErr;
       
   106 	}
       
   107 
       
   108 // State change utility function
       
   109 
       
   110 void TRfcommState::ChangeState(CRfcommSAP& aSAP, CRfcommStateFactory::TRfcommStates aNewState) const
       
   111 	{
       
   112 	aSAP.iState->Exit(aSAP);
       
   113 #ifdef __FLOG_ACTIVE
       
   114 	TRfcommState* state= iFactory.GetState(aNewState);
       
   115 	LOG3(_L("RFCOMM : Sap %08x : State %S -> %S"),
       
   116 				  &aSAP, &aSAP.iState->iName, &state->iName);
       
   117 #endif //__FLOG_ACTIVE
       
   118 	aSAP.iState=iFactory.GetState(aNewState);
       
   119 	aSAP.iState->Enter(aSAP);
       
   120 	}
       
   121 
       
   122 void TRfcommState::PanicInState(TRFCOMMPanic aPanic) const
       
   123 	{
       
   124 	Panic(aPanic, iFactory.StateIndex(this));
       
   125 	}
       
   126 
       
   127 #ifdef _DEBUG
       
   128 void TRfcommState::DebugPanicInState(TRFCOMMPanic aPanic) const
       
   129 #else
       
   130 void TRfcommState::DebugPanicInState(TRFCOMMPanic /*aPanic*/) const
       
   131 #endif
       
   132 	{
       
   133 	#ifdef _DEBUG
       
   134 	PanicInState(aPanic);
       
   135 	#endif
       
   136 	}
       
   137 
       
   138 TRfcommState::TRfcommState(CRfcommStateFactory& aFactory)
       
   139 	: iFactory(aFactory)
       
   140 	{
       
   141 	}
       
   142 
       
   143 /************************************************************************/
       
   144 /*
       
   145    The default state operations.
       
   146 */
       
   147 
       
   148 TRfcommStateDefault::TRfcommStateDefault(CRfcommStateFactory& aFactory)
       
   149 	: TRfcommState(aFactory)
       
   150 	{
       
   151 	}
       
   152 
       
   153 void TRfcommStateDefault::Enter(CRfcommSAP& /*aSAP*/)
       
   154 	{
       
   155 	// Do nothing
       
   156 	}
       
   157 
       
   158 void TRfcommStateDefault::Exit(CRfcommSAP& /*aSAP*/)
       
   159 	{
       
   160 	// Do nothing
       
   161 	}
       
   162 	
       
   163 void TRfcommStateDefault::ActiveOpen(CRfcommSAP& /* aSAP */ )
       
   164 	{
       
   165 	PanicInState(ERfcommUnexpectedEvent);
       
   166 	}
       
   167 
       
   168 TInt TRfcommStateDefault::PassiveOpen(CRfcommSAP& /* aSAP */,
       
   169 									  TUint /*aQueSize*/)
       
   170 	{
       
   171 	PanicInState(ERfcommUnexpectedEvent);
       
   172 	return KErrGeneral;
       
   173 	}
       
   174 
       
   175 
       
   176 void TRfcommStateDefault::Shutdown(CRfcommSAP& aSAP)
       
   177 	{
       
   178 	SignalError(aSAP, KErrRfcommSAPUnexpectedEvent, MSocketNotify::EErrorAllOperations);
       
   179 	}
       
   180 
       
   181 void TRfcommStateDefault::FastShutdown(CRfcommSAP& aSAP)
       
   182 	{
       
   183 	SignalError(aSAP, KErrRfcommSAPUnexpectedEvent, MSocketNotify::EErrorAllOperations);
       
   184 	}
       
   185 
       
   186 
       
   187 TInt TRfcommStateDefault::Send(CRfcommSAP& /*aSAP*/, const TDesC8& /*aData*/ )
       
   188 	{
       
   189 	PanicInState(ERfcommUnexpectedEvent);
       
   190 	return 0;
       
   191 	}
       
   192 
       
   193 void TRfcommStateDefault::Read(CRfcommSAP& /*aSAP*/, TDesC8& /*aData*/)
       
   194 	{
       
   195 	PanicInState(ERfcommUnexpectedEvent);
       
   196 	}
       
   197 
       
   198 void TRfcommStateDefault::Ioctl(CRfcommSAP& aSAP, TUint /*aLevel*/,
       
   199 								TUint /*aName*/, TDes8* /*aOption*/)
       
   200 	{
       
   201 	SignalError(aSAP, KErrNotSupported, MSocketNotify::EErrorIoctl);
       
   202 	}
       
   203 
       
   204 void TRfcommStateDefault::CancelIoctl(CRfcommSAP& aSAP, TUint /*aLevel*/, TUint /*aName*/)
       
   205 	/**
       
   206 	   A request to cancel an Ioctl.
       
   207 	   
       
   208 	   Since the user has already been completed, and ESOCK prevents
       
   209 	   the completion occuring twice, there's very little we need to
       
   210 	   do (in fact we could ignore this entirely).
       
   211 	   
       
   212 	   Instead we will simply reset out IoctlLevel and IoctlName,
       
   213 	   since this will now mean that we will not complete the ioctl
       
   214 	   when the complete signal comes in.  If the ioctl is going on
       
   215 	   below us, we will ignore the ioctl complete from them as well.
       
   216 	**/
       
   217  	{
       
   218 	aSAP.iIoctlLevel=0;
       
   219 	aSAP.iIoctlName=0;
       
   220  	}
       
   221 
       
   222 void TRfcommStateDefault::Start(CRfcommSAP& /*aSAP*/)
       
   223 	{
       
   224 	PanicInState(ERfcommUnexpectedEvent);
       
   225 	}
       
   226 
       
   227 TInt TRfcommStateDefault::SetOption(CRfcommSAP &aSAP, TUint aLevel, 
       
   228 								   TUint aName, const TDesC8& aOption)
       
   229 	/**
       
   230 	   Set Option from user - works the same for SAPs in all states.
       
   231 	**/
       
   232 	{
       
   233 	if(aLevel == KSolBtRFCOMM)
       
   234 		{
       
   235 		switch(aName)
       
   236 			{
       
   237 		case KRFCOMMLocalPortParameter:
       
   238 			// Just do a straight copy into the local port params
       
   239 			aSAP.iLocalPortParams = *(TRfcommRemotePortParams*)aOption.Ptr();
       
   240 			break;
       
   241 		case KRFCOMMMaximumSupportedMTU:
       
   242     		{
       
   243 			if ( aOption.Length() != sizeof(TUint16) )
       
   244 				{
       
   245 				return KErrArgument;
       
   246 				}
       
   247 			else
       
   248 				{
       
   249 				TPckgBuf<TUint16> maxMTU;
       
   250 				maxMTU.Copy(aOption);
       
   251 				aSAP.iUserDefinedMTU = maxMTU();
       
   252 				}
       
   253 			};
       
   254 			break;
       
   255 
       
   256 		case KRFCOMMFlowTypeCBFC:
       
   257 			{
       
   258 			if ( aOption.Length() != sizeof(TBool) )
       
   259 				{
       
   260 				return KErrArgument;
       
   261 				}
       
   262 			else
       
   263 				{
       
   264 				TPckgBuf<TBool> aCBFC;
       
   265 				aCBFC.Copy(aOption);
       
   266 				if(!aCBFC())
       
   267 					{
       
   268 					//Switch off CBFC facility by setting flow strategy to
       
   269 					//non-CBFC and setting the flow negotiated flag to 'ETrue'.
       
   270 					if(aSAP.iMux)
       
   271 						{
       
   272 						if(!aSAP.iMux->SetFlowType(CRfcommFlowStrategyFactory::EFlowNonCreditBased))
       
   273 							{
       
   274 							return KErrNotSupported;
       
   275 							}
       
   276 						}
       
   277 					else
       
   278 						{
       
   279 						aSAP.DisallowCBFC(); //will cause muxer to use muxwise CBFC when created
       
   280 						}
       
   281 					}
       
   282 				else
       
   283 					{
       
   284 					//Switch on CBFC facility by setting flow strategy to
       
   285 					//CBFC and setting the flow negotiated flag to 'ETrue'.
       
   286 					if(aSAP.iMux)
       
   287 						{
       
   288 						if(!aSAP.iMux->SetFlowType(CRfcommFlowStrategyFactory::EFlowCreditBased))
       
   289 							{
       
   290 							return KErrNotSupported;
       
   291 							}
       
   292 						}
       
   293 					else
       
   294 						{
       
   295 						aSAP.AllowCBFC(); //will cause muxer to use muxwise CBFC when created
       
   296 						}
       
   297 					}
       
   298 				}
       
   299 			}
       
   300 			break;
       
   301 		case KRFCOMMErrOnMSC:
       
   302 			{
       
   303 			if ( aOption.Length() != sizeof(TUint8) )
       
   304 				{
       
   305 				return KErrArgument;
       
   306 				}
       
   307 			else
       
   308 				{
       
   309 				TPckgBuf<TUint8> aSignal;
       
   310 				aSignal.Copy(aOption);
       
   311 				aSAP.iDisconnectMSCSignal = aSignal();
       
   312 				}
       
   313 			}
       
   314 			break;
       
   315 		case KBTSecurityDeviceOverride:
       
   316 			{
       
   317 			// let the security object handle this
       
   318 			return aSAP.SetDeviceOverride(aOption); // just pass the option
       
   319 			}
       
   320 		case KBTRegisterCodService:
       
   321 			{
       
   322 			TInt err = KErrNone;
       
   323 	        TUint16 newServiceBits = *reinterpret_cast<const TUint16*>(aOption.Ptr());
       
   324 			err = aSAP.SetCodServiceBits(newServiceBits);	// The service bits are saved and then registered when SAP becomes live
       
   325 			return err;
       
   326 			}
       
   327 
       
   328 		case KRFCOMMForgiveCBFCOverflow:
       
   329     		{
       
   330 			if ( aOption.Length() != sizeof(TBool) )
       
   331 				{
       
   332 				return KErrArgument;
       
   333 				}
       
   334 			else
       
   335 				{
       
   336 				aSAP.iForgiveCBFCOverflow = *reinterpret_cast<const TBool*>(aOption.Ptr());
       
   337 				}
       
   338 			};
       
   339 			break;
       
   340 
       
   341 		default:
       
   342 			return KErrNotSupported;
       
   343 			}
       
   344 		return KErrNone;
       
   345 		}
       
   346 
       
   347 	// Not a RFCOMM setopt so error.  We don't support passdown (yet).
       
   348 	return KErrNotSupported;	
       
   349 	}
       
   350 	
       
   351 void TRfcommStateDefault::MuxUp(CRfcommSAP& aSAP)
       
   352 	{
       
   353 	SignalError(aSAP, KErrRfcommSAPUnexpectedEvent,
       
   354 				MSocketNotify::EErrorAllOperations);
       
   355 	}
       
   356 
       
   357 void TRfcommStateDefault::LinkDown(CRfcommSAP& aSAP)
       
   358 	{
       
   359 	SignalError(aSAP, KErrRfcommSAPUnexpectedEvent,
       
   360 				MSocketNotify::EErrorAllOperations);
       
   361 	}
       
   362 
       
   363 void TRfcommStateDefault::SABM(CRfcommSAP& /*aSAP*/, CRfcommMuxer& aMux, TUint8 aDLCI)
       
   364 	/**
       
   365 	   Send a DM, since we are not expecting this
       
   366 	
       
   367 	**/
       
   368 	{
       
   369 	aMux.SendDM(aDLCI);
       
   370 	}
       
   371 
       
   372 void TRfcommStateDefault::DISC(CRfcommSAP& aSAP)
       
   373 	/**
       
   374 	   Send a DM as we were not expecting this
       
   375 	**/
       
   376 	{
       
   377 	aSAP.iMux->SendDM(aSAP.iDLCI);
       
   378 	}
       
   379 
       
   380 void TRfcommStateDefault::UA(CRfcommSAP& /*aSAP*/)
       
   381 	/**
       
   382 	   Do nothing - unexpected response
       
   383 	**/
       
   384 	{
       
   385 	}
       
   386 
       
   387 void TRfcommStateDefault::DM(CRfcommSAP& /*aSAP*/)
       
   388 	/**
       
   389 	   Do nothing - unexpected response
       
   390 	**/
       
   391 	{
       
   392 	}
       
   393 	
       
   394 void TRfcommStateDefault::RPN(CRfcommSAP& aSAP, const TRfcommRPNTransaction& /*aRPNTransaction*/, CRfcommMuxer& /*aMuxer*/, TUint8 /*aDLCI*/)
       
   395 	/**
       
   396 	   Send a DM as we didn't expect this
       
   397 	**/
       
   398  	{
       
   399 	aSAP.iMux->SendDM(aSAP.iDLCI);
       
   400  	}
       
   401  
       
   402 void TRfcommStateDefault::RPNRsp(CRfcommSAP& /*aSAP*/, 
       
   403 								const TRfcommRPNTransaction& 
       
   404 								/*aRPNTransaction*/)
       
   405 	/**
       
   406 	   Do nothing - unwanted response
       
   407 	**/
       
   408  	{
       
   409  	}
       
   410 
       
   411 
       
   412 void TRfcommStateDefault::PN(CRfcommSAP& aSAP, TRfcommPortParams& /*aParams*/, CRfcommMuxer& /*aMux*/, TUint8 aDLCI)
       
   413 	/**
       
   414 	   Send a DM as we aren't handling this.
       
   415 	**/
       
   416 	{
       
   417 	__ASSERT_DEBUG(aDLCI==aSAP.iDLCI, PanicInState(ERfcommPNMismatchedDLCI));
       
   418 	aSAP.iMux->SendDM(aDLCI);
       
   419 	}
       
   420 
       
   421 void TRfcommStateDefault::PNResp(CRfcommSAP& /*aSAP*/, TRfcommPortParams& /*aParams*/)
       
   422 	/**
       
   423 	   Do nothing - unwanted response
       
   424 	**/
       
   425 	{
       
   426 	}
       
   427 
       
   428 void TRfcommStateDefault::MSC(CRfcommSAP& /*aSAP*/, TUint8 /*aSignals*/)
       
   429 	/**
       
   430 	   Do nothing - the response is autogenerated
       
   431 	**/
       
   432 	{
       
   433 	}
       
   434 
       
   435 void TRfcommStateDefault::RLS(CRfcommSAP& /*aSAP*/, TUint8 /*aStatus*/)
       
   436 	/**
       
   437 	   Do nothing - the response is autogenerated
       
   438 	**/
       
   439  	{
       
   440  	}
       
   441 	
       
   442 void TRfcommStateDefault::NewData(CRfcommSAP& /*aSAP*/, const TDesC8& /*aData*/)
       
   443 	/**
       
   444 	   Do nothing - we're throwing this data away
       
   445 	**/
       
   446 	{
       
   447 	}
       
   448 
       
   449 void TRfcommStateDefault::NotifyNewDataCallback(CRfcommSAP& aSAP)
       
   450 	{
       
   451 	SignalError(aSAP, KErrRfcommSAPUnexpectedEvent, MSocketNotify::EErrorAllOperations);
       
   452 	}
       
   453 
       
   454 void TRfcommStateDefault::CanSend(CRfcommSAP& aSAP)
       
   455 	{
       
   456 	SignalError(aSAP, KErrRfcommSAPUnexpectedEvent, MSocketNotify::EErrorAllOperations);
       
   457 	}
       
   458 
       
   459 void TRfcommStateDefault::IoctlComplete(CRfcommSAP& /*aSAP*/, TInt /*aErr*/, TUint /*aLevel*/, TUint /*aName*/, TDesC8* /*aBuf*/)
       
   460 	{
       
   461 	// Do nothing, this isn't for us
       
   462 	}
       
   463 
       
   464 void TRfcommStateDefault::AccessRequestComplete(CRfcommSAP& /*aSAP*/, TInt /*aResult*/)
       
   465 	{
       
   466 	PanicInState(ERfcommUnexpectedSecurityRequesterCallback);
       
   467 	}
       
   468 
       
   469 void TRfcommStateDefault::Error(CRfcommSAP& aSAP, TInt aErr,
       
   470 								CRfcommSAP::TErrorTypes /*aType*/)
       
   471 	{
       
   472 	SignalError(aSAP, aErr,
       
   473 				MSocketNotify::EErrorAllOperations);
       
   474 	}
       
   475 
       
   476 void TRfcommStateDefault::ParentClosed(CRfcommSAP& aSAP)
       
   477 	/**
       
   478 	Our parent SAP has been deleted - NULL our pointer to it.
       
   479 
       
   480 	This function only really applies to cloned child SAPs, but we
       
   481 	handle it here anyway.
       
   482 	**/
       
   483 	{
       
   484 	aSAP.iParentSAP=NULL;
       
   485 	}
       
   486 
       
   487 TBool TRfcommStateDefault::HandleFrameResponseTimeout(CRfcommSAP& /*aSAP*/)
       
   488 	{
       
   489 	//	By default, we refuse to handle the frame timeout, indicating this by
       
   490 	//	returning EFalse.
       
   491 	return EFalse;
       
   492 	}
       
   493 
       
   494 //TRY_CBFC
       
   495 TUint8 TRfcommStateDefault::FreeCredit(CRfcommSAP& /*aSAP*/)
       
   496 	{
       
   497 	// return the max initial credit
       
   498 	return (TUint8)KInitialCredit;
       
   499 	}
       
   500 
       
   501 TInt TRfcommStateDefault::ProxyForRemoteCredit(const CRfcommSAP& /*aSAP*/) const
       
   502 	{
       
   503 	// return the max initial credit
       
   504 	return (TInt)KInitialCredit;
       
   505 	}
       
   506 
       
   507 void TRfcommStateDefault::SetProxyForRemoteCredit(CRfcommSAP& aSAP, TInt aCredit)
       
   508 	{
       
   509 	aSAP.iProxyForRemoteCredit = aCredit;
       
   510 	LOG1(_L("RFCOMM: Proxy for credits available on REMOTE (...NEW SETUP...) -> %d"), aSAP.iProxyForRemoteCredit);
       
   511 	}
       
   512 
       
   513 void TRfcommStateDefault::ProxyForRemoteCreditDecrement(CRfcommSAP& aSAP)
       
   514 	{
       
   515 	__ASSERT_DEBUG(aSAP.iProxyForRemoteCredit > 0,PanicInState(ERfcommCBFCProxyForRemoteCreditGoingNegative));
       
   516 
       
   517 	aSAP.iProxyForRemoteCredit--;
       
   518 	LOG(_L("RFCOMM: Proxies for CREDITS on REMOTE:-"));
       
   519 	LOG2(_L("RFCOMM:     Available for use  (...DECREMENT...) %d -> %d: -1"), 
       
   520 				  aSAP.iProxyForRemoteCredit+1,
       
   521 				  aSAP.iProxyForRemoteCredit);
       
   522 	#ifdef _DEBUG
       
   523 	aSAP.iProxyForRemoteCreditsUsed++;
       
   524 	LOG1(_L("RFCOMM:     Total USED so far during this session: %d"), 
       
   525 				  aSAP.iProxyForRemoteCreditsUsed);
       
   526 	#endif
       
   527 	return;
       
   528 	}
       
   529 
       
   530 void TRfcommStateDefault::ProxyForRemoteCreditAddCredit(CRfcommSAP& aSAP, TUint8 aCredit)
       
   531 	{
       
   532 	aSAP.iProxyForRemoteCredit += aCredit;
       
   533 	LOG(_L("RFCOMM: Proxies for CREDITS on REMOTE:-"));
       
   534 	LOG3(_L("RFCOMM:     Available for use  (...ADD...) %d -> %d: +%d"), 
       
   535 				  aSAP.iProxyForRemoteCredit-aCredit,
       
   536 				  aSAP.iProxyForRemoteCredit,
       
   537 				  aCredit);
       
   538 	#ifdef _DEBUG
       
   539 	aSAP.iProxyForRemoteCreditsSupplied += aCredit;
       
   540 	LOG1(_L("RFCOMM:     Total SUPPLIED so far during this session: %d"), 
       
   541 				  aSAP.iProxyForRemoteCreditsSupplied);
       
   542 	#endif
       
   543 	}
       
   544 
       
   545 
       
   546 TInt TRfcommStateDefault::LocalCredit(const CRfcommSAP& /*aSAP*/) const
       
   547 	{
       
   548 	// return a zero credit - so cannot send
       
   549 	return (TInt)0;
       
   550 	}
       
   551 
       
   552 void TRfcommStateDefault::SetInitialLocalCredit(CRfcommSAP& aSAP, TInt aCredit)
       
   553 	{
       
   554 	aSAP.iLocalCredit = aCredit;
       
   555 	LOG1(_L("RFCOMM: LOCAL credits available (...NEW SETUP...) -> %d"), aSAP.iLocalCredit);
       
   556 	}
       
   557 
       
   558 void TRfcommStateDefault::LocalCreditDecrement(CRfcommSAP& aSAP)
       
   559 	{
       
   560 	__ASSERT_DEBUG(aSAP.iLocalCredit > 0,PanicInState(ERfcommCBFCLocalCreditGoingNegative));
       
   561 	
       
   562 	aSAP.iLocalCredit--;
       
   563 	LOG(_L("RFCOMM: LOCAL CREDITS:-"));
       
   564 	LOG2(_L("RFCOMM:     Available for use (...DECREMENT...) %d -> %d: -1"), 
       
   565 				  aSAP.iLocalCredit+1,
       
   566 				  aSAP.iLocalCredit);
       
   567 	#ifdef _DEBUG
       
   568 	aSAP.iLocalCreditsUsed++;
       
   569 	LOG1(_L("RFCOMM:     Total USED so far during this session: %d"), 
       
   570 				  aSAP.iLocalCreditsUsed);
       
   571 	#endif
       
   572 	return;
       
   573 	}
       
   574 
       
   575 void TRfcommStateDefault::LocalCreditAddCredit(CRfcommSAP& aSAP, TUint8 aCredit)
       
   576 	{
       
   577 	aSAP.iLocalCredit += aCredit;
       
   578 	LOG(_L("RFCOMM: LOCAL CREDITS:-"));
       
   579 	LOG3(_L("RFCOMM:     Available for use (...ADD...) %d -> %d: +%d"), 
       
   580 				  aSAP.iLocalCredit-aCredit,
       
   581 				  aSAP.iLocalCredit,
       
   582 				  aCredit);
       
   583 	#ifdef _DEBUG
       
   584 	aSAP.iLocalCreditsSupplied += aCredit;
       
   585 	LOG1(_L("RFCOMM:     Total SUPPLIED so far during this session: %d"), 
       
   586 				  aSAP.iLocalCreditsSupplied);
       
   587 	#endif
       
   588 	}
       
   589 
       
   590 
       
   591 /*************************************************************************/
       
   592 
       
   593 //  TRfcommStateError
       
   594 
       
   595 /*************************************************************************/
       
   596 
       
   597 TRfcommStateError::TRfcommStateError(CRfcommStateFactory& aFactory)
       
   598 	: TRfcommStateDefault(aFactory)
       
   599 	{
       
   600 	STATENAME("Error");
       
   601 	}
       
   602 
       
   603 void TRfcommStateError::ActiveOpen(CRfcommSAP& aSAP)
       
   604 	{
       
   605 	SignalError(aSAP, KErrGeneral, MSocketNotify::EErrorAllOperations);
       
   606 	}
       
   607 
       
   608 TInt TRfcommStateError::PassiveOpen(CRfcommSAP& aSAP, TUint /*aQueSize*/)
       
   609 	{
       
   610 	return SignalError(aSAP,KErrGeneral, MSocketNotify::EErrorAllOperations);
       
   611 	}
       
   612 
       
   613 void TRfcommStateError::Shutdown(CRfcommSAP& aSAP)
       
   614 	{
       
   615 	SignalError(aSAP,KErrGeneral, MSocketNotify::EErrorAllOperations);
       
   616 	}
       
   617 
       
   618 void TRfcommStateError::FastShutdown(CRfcommSAP& aSAP)
       
   619 	{
       
   620 	SignalError(aSAP,KErrGeneral, MSocketNotify::EErrorAllOperations);
       
   621 	}
       
   622 
       
   623 TInt TRfcommStateError::Send(CRfcommSAP& aSAP, const TDesC8&)
       
   624 	{
       
   625 	SignalError(aSAP,KErrGeneral, MSocketNotify::EErrorAllOperations);
       
   626 	return 0;
       
   627 	}
       
   628 
       
   629 void TRfcommStateError::Read(CRfcommSAP& aSAP, TDesC8&)
       
   630 	{
       
   631 	SignalError(aSAP,KErrGeneral, MSocketNotify::EErrorAllOperations);
       
   632 	}
       
   633 
       
   634 void TRfcommStateError::Ioctl(CRfcommSAP& aSAP, TUint, TUint, TDes8*)
       
   635 	{
       
   636 	SignalError(aSAP,KErrGeneral, MSocketNotify::EErrorAllOperations);
       
   637 	}
       
   638 
       
   639 void TRfcommStateError::CancelIoctl(CRfcommSAP& /*aSAP*/, TUint, TUint)
       
   640 	/**
       
   641 	   Ignore the cancel.
       
   642 	   
       
   643 	   This is because cancelling in the error state may even be
       
   644 	   valid, and it doesn't hurt to ignore cancels.
       
   645 	**/
       
   646 	{
       
   647 	}
       
   648 
       
   649 void TRfcommStateError::Start(CRfcommSAP& aSAP)
       
   650 	{
       
   651 	SignalError(aSAP,KErrGeneral, MSocketNotify::EErrorAllOperations);
       
   652 	}
       
   653 
       
   654 void TRfcommStateError::Enter(CRfcommSAP& aSAP)
       
   655 	/**
       
   656 	   Take this SAP off the mux, since once it's in error state we
       
   657 	   don't want to get any more notifications from the mux
       
   658 	**/
       
   659 	{
       
   660 
       
   661 	aSAP.DeregisterCodService();	// See if there is a Service to remove for CodMan
       
   662 	
       
   663 	if(aSAP.iMux)
       
   664 		{
       
   665 		aSAP.iMux->DetachSAP(aSAP);
       
   666 		}
       
   667 	}
       
   668 	  
       
   669 
       
   670 /*************************************************************************/
       
   671 
       
   672 // Implementation of TRfcommStateClosed
       
   673 //
       
   674 // This is the intial state for a SAP and represents it before Connect() has
       
   675 // been called, and it is also the end state when closing down
       
   676 
       
   677 TRfcommStateClosed::TRfcommStateClosed(CRfcommStateFactory& aFactory)
       
   678 	: TRfcommStateDefault(aFactory)
       
   679 	{
       
   680 	STATENAME("Closed");
       
   681 	}
       
   682 
       
   683 void TRfcommStateClosed::Enter(CRfcommSAP& aSAP)
       
   684 	/**
       
   685 	   Entering the closed state.
       
   686 
       
   687 	   We need to remove ourselves from the muxer (if we have one)
       
   688 	**/
       
   689 	{
       
   690 	aSAP.iClosePending=EFalse;
       
   691 	if(aSAP.iNotifyNewDataCallback->IsActive())
       
   692 		{
       
   693 		aSAP.iNotifyNewDataCallback->Cancel();
       
   694 		}
       
   695 	aSAP.iNewDataToNotify=0;
       
   696 	aSAP.iDataBuffer.Reset();
       
   697 	aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EUndoOverridePark, aSAP.iRemoteDev);
       
   698 	if(aSAP.iMux)
       
   699 		{
       
   700 		aSAP.iMux->DetachSAP(aSAP);
       
   701 		}
       
   702 	aSAP.DeregisterCodService();	// See if there is a Service to remove for CodMan
       
   703 		
       
   704 	}
       
   705 
       
   706 void TRfcommStateClosed::Error(CRfcommSAP& /*aSAP*/, TInt /*aErr*/, 
       
   707 							   CRfcommSAP::TErrorTypes /*aType*/)
       
   708 	/**
       
   709 	   Panic, we'd never get here since state closed never has a mux associated.
       
   710 	**/
       
   711 	{
       
   712 	DebugPanicInState(ERfcommUnexpectedEvent);
       
   713 	}
       
   714 
       
   715 void TRfcommStateClosed::ActiveOpen(CRfcommSAP& aSAP)
       
   716 	/**
       
   717 	   Called by Socket to cause a connection to be established.
       
   718 	   
       
   719 	   This causes a sequence of actions which ends with
       
   720 	   ConnectComplete() being called on the socket notifier.  Since a
       
   721 	   SAP in the closed state may not be fully initialised, all the
       
   722 	   parameters must be checked before starting the connect.
       
   723 	**/	   
       
   724 	{
       
   725 	LOG1(_L("RFCOMM: ActiveOpen while state closed, sap %08x"), &aSAP);
       
   726 	if(!aSAP.ServerChannelValid() )
       
   727 		{
       
   728 		LOG(_L("SAP DLCI error"));
       
   729 		SignalError(aSAP, KErrRfcommBadAddress, MSocketNotify::EErrorConnect);
       
   730 		return;
       
   731 		}
       
   732 
       
   733 	aSAP.RegisterCodService();	// See if there is a Service set for CodMan
       
   734 		
       
   735 	// First get a Mux.
       
   736 	ChangeState(aSAP, CRfcommStateFactory::EWaitForMux);
       
   737 	}
       
   738 
       
   739 TInt TRfcommStateClosed::PassiveOpen(CRfcommSAP& aSAP, 
       
   740 									 TUint aQueSize)
       
   741 	/**
       
   742 	We've just asked to turn into a listening SAP.
       
   743 
       
   744 	NB. We need to check with the protocol that no other listening SAPs
       
   745 	are currently listening on our specified server channel.
       
   746 	We should also return an error if the protocol has no listener
       
   747 	**/
       
   748 	{
       
   749 	//	First, check that the protocol is listening
       
   750 
       
   751 	if(aSAP.iProtocol.IncrementListeners() != KErrNone)	// get protocol to attempt to listen
       
   752 		return KErrRfcommNotListening;
       
   753 
       
   754 	//	Second, the check for other listening SAPs on our specified local address.
       
   755 
       
   756 	TBTSockAddr listeningName;
       
   757 	aSAP.LocalName(listeningName);
       
   758 	CRfcommSAP* listener=aSAP.iProtocol.FindIdleSAP(listeningName);
       
   759 
       
   760 	__ASSERT_DEBUG((listener==NULL), PanicInState(ERfcommSAPAllocatedBetweenBindAndListen));
       
   761 
       
   762 	if(listener!=NULL)
       
   763 		return KErrInUse;
       
   764 	
       
   765 	TBTSockAddr remoteAddr;
       
   766 	remoteAddr.SetBTAddr(aSAP.iRemoteDev);
       
   767 	remoteAddr.SetPort(aSAP.iServerChannel);
       
   768 	if(aSAP.iProtocol.FindIdleSAP(remoteAddr))
       
   769 		return KErrAlreadyExists;	//	RFCOMM already has a listener which would field this address...
       
   770 
       
   771 	aSAP.iMaxClonesWaitingForStart=aQueSize;
       
   772 	aSAP.RegisterCodService();	// See if there is a Service set for CodMan
       
   773 	ChangeState(aSAP, CRfcommStateFactory::EListening);
       
   774 	return KErrNone;
       
   775 	}
       
   776 
       
   777 void TRfcommStateClosed::Start(CRfcommSAP& /*aSAP*/)
       
   778 	{
       
   779 	//	Do nothing - this is quite a valid thing to happen, but the base class panics!
       
   780 	}
       
   781 
       
   782 void TRfcommStateClosed::Shutdown(CRfcommSAP& aSAP)
       
   783 	/**
       
   784 	   The ESOCK would like us to close down.  We can.
       
   785 	**/
       
   786 	{
       
   787 	aSAP.iSocket->CanClose();
       
   788 	}
       
   789 
       
   790 TInt TRfcommStateClosed::SetOption(CRfcommSAP &aSAP, TUint aLevel, 
       
   791 								   TUint aName, const TDesC8& aOption)
       
   792     /**
       
   793        Allow modem status to be modified whilst we are closed.
       
   794     **/
       
   795     {
       
   796 	if(aLevel == KSolBtRFCOMM && aName == KRFCOMMLocalModemStatus)
       
   797         {
       
   798 		if ( aOption.Length() != sizeof(TUint8) )
       
   799 			{
       
   800 			return KErrArgument;
       
   801 			}
       
   802 		else
       
   803 			{
       
   804 			TPckgBuf<TUint8> signals;
       
   805 			signals.Copy(aOption);
       
   806 			aSAP.iSignals = signals();
       
   807 			return KErrNone;
       
   808 			}
       
   809         }
       
   810 
       
   811     return TRfcommStateDefault::SetOption(aSAP, aLevel, aName, aOption);
       
   812     }
       
   813 
       
   814 /*************************************************************************/
       
   815 
       
   816 // Implementation of TRfcommStateConnecting
       
   817 
       
   818 TRfcommStateConnecting::TRfcommStateConnecting(CRfcommStateFactory& aFactory)
       
   819 	: TRfcommStateDefault(aFactory)
       
   820 	{
       
   821 	}
       
   822 
       
   823 
       
   824 void TRfcommStateConnecting::Shutdown(CRfcommSAP&  aSAP)
       
   825 /**
       
   826 	We've been asked to do a controlled shutdown during connection.
       
   827 	Record the fact that we want to send a disconnect command upon
       
   828 	reception of the UA command.
       
   829 **/	
       
   830 	{
       
   831 	aSAP.iClosePending=ETrue;
       
   832 	}
       
   833 
       
   834 void TRfcommStateConnecting::FastShutdown(CRfcommSAP&  aSAP)
       
   835 /**
       
   836 	We've been asked to shutdown with extreme prejudice.
       
   837 	Move back to the Closed state - there is nothing we can do
       
   838 	to make this clean
       
   839 **/
       
   840 	{
       
   841 	ChangeState(aSAP, CRfcommStateFactory::EClosed);
       
   842 	};
       
   843 
       
   844 
       
   845 void TRfcommStateConnecting::DM(CRfcommSAP& aSAP)
       
   846 /**
       
   847 	We've received a DM (Disconnect Mode) response.
       
   848 	If we've been asked to close down anyway, tell the SAP that we can be closed.
       
   849 	If we haven't, signal an error to the socket.
       
   850 **/
       
   851 	{
       
   852 	FailureWhileConnecting(aSAP, KErrCouldNotConnect);	
       
   853 	}
       
   854 
       
   855 void TRfcommStateConnecting::FailureWhileConnecting(CRfcommSAP& aSAP, TInt aErrorCode)
       
   856 /**
       
   857 	Send appropriate notification of failure back to SAP socket if failure occurs while connecting.
       
   858 **/
       
   859 	{
       
   860 	if(!aSAP.iClosePending)
       
   861 		{
       
   862 		ChangeState(aSAP, CRfcommStateFactory::EClosed);
       
   863 		SignalError(aSAP, aErrorCode, MSocketNotify::EErrorConnect);
       
   864 		}
       
   865 	else
       
   866 		{
       
   867 		aSAP.iSocket->CanClose();  // Will delete us
       
   868 		}
       
   869 	}
       
   870 
       
   871 void TRfcommStateConnecting::LinkDown(CRfcommSAP& aSAP)
       
   872 	/**
       
   873 	   The link has gone down before our connection came up.
       
   874 
       
   875 	   This can even (counter-intuitively) occur in WaitForMux because
       
   876 	   there is a lag between the l2cap link coming up and the mux
       
   877 	   channel itself coming up.  In the interval, the l2cap link can
       
   878 	   drop again and thus we get a link down notification (the mux
       
   879 	   will not attempt to reconnect).
       
   880 
       
   881 	   Handle this by simply erroring the connection attempt.
       
   882 	**/
       
   883 	{
       
   884 	// tell secman not to bother
       
   885 	aSAP.CancelAccessRequest();
       
   886 
       
   887 	FailureWhileConnecting(aSAP, KErrDisconnected);
       
   888 	}
       
   889 
       
   890 
       
   891 /*******************************************************************/
       
   892 /*
       
   893   Implementation of WaitForMux state.
       
   894   When a mux has been found for this SAP, then MuxUp is called.
       
   895 */
       
   896 
       
   897 TRfcommStateWaitForMux::TRfcommStateWaitForMux(CRfcommStateFactory& aFactory)
       
   898 	: TRfcommStateConnecting(aFactory)
       
   899 	{
       
   900 	STATENAME("WaitForMux");
       
   901 	}
       
   902 
       
   903 void TRfcommStateWaitForMux::Enter(CRfcommSAP& aSAP)
       
   904 	/**
       
   905 	   Entry to the state.
       
   906 
       
   907 	   Ask the protocol to find a mux for us. We can then
       
   908 	   add our context to it.
       
   909 	**/
       
   910 	{
       
   911 	CRfcommMuxer* mux=NULL;
       
   912 	TBTSockAddr remoteAddr;
       
   913 	aSAP.RemName(remoteAddr);
       
   914 	TInt error=aSAP.iProtocol.GetMux(remoteAddr,mux);
       
   915 	if(error)
       
   916 		Error(aSAP, error, CRfcommSAP::EErrorGeneral);
       
   917 	else
       
   918 		{
       
   919 		//	Calculate the DLCI that this SAP is trying to connect to
       
   920 		aSAP.iDLCI=mux->MakeOutboundDLCI(TUint8(remoteAddr.Port()));
       
   921 		//	Ensure that we don't already have a connection for the DLCI
       
   922 		//	we're trying to connect to on this device...
       
   923 		if(mux->FindSAP(aSAP.DLCI())!=NULL)
       
   924 			{
       
   925 			//	Problems! We've already got a SAP attached to this DLCI
       
   926 			//	for this same device...we need to error this SAP.
       
   927 			LOG1(_L("RFCOMM: Attempt to connect to connected SAP, DLCI %d"), aSAP.DLCI());
       
   928 			Error(aSAP, KErrAlreadyExists, CRfcommSAP::EErrorGeneral);
       
   929 			}
       
   930 		else
       
   931 			{
       
   932 			// Transfer the sap to the mux
       
   933 			if(aSAP.iMux)
       
   934 				aSAP.iLink.Deque();
       
   935 			aSAP.iMux=mux;
       
   936 
       
   937 			//	The next line will call back into MuxUp, either synchronously 
       
   938 			//	(when mux channel is already up) or asynchronously (when the
       
   939 			//	mux channel needs to be opened).
       
   940 			mux->AddSAP(aSAP);  
       
   941 			}
       
   942 		}
       
   943 	}
       
   944 	
       
   945 void TRfcommStateWaitForMux::MuxUp(CRfcommSAP& aSAP)
       
   946 	/**
       
   947 	   A muxer has been found for this SAP.
       
   948 	   On entry, the sap has had a muxer associated with it.
       
   949 	   Change state to connecting, so it can do any config and the SABM.
       
   950 	**/
       
   951 	{
       
   952 	ChangeState(aSAP, CRfcommStateFactory::EWaitForPNResp); // Enter the new state
       
   953 	}
       
   954 
       
   955 void TRfcommStateWaitForMux::Shutdown(CRfcommSAP& aSAP)
       
   956 	/**
       
   957 	   We've been asked to shutdown while connecting.
       
   958 
       
   959 	   Since the mux isn't up yet, we must detach from the mux and
       
   960 	   also signal that we can be deleted.
       
   961 	**/
       
   962 	{
       
   963 	ChangeState(aSAP, CRfcommStateFactory::EClosed);// Enter this state, which detaches us
       
   964 	aSAP.iSocket->CanClose();  // This deletes us
       
   965 	}
       
   966 
       
   967 void TRfcommStateWaitForMux::SABM(CRfcommSAP& aSAP, CRfcommMuxer& /*aMux*/, TUint8 /*aDLCI*/)
       
   968 	{
       
   969 	DebugPanicInState(ERfcommFrameBeforeMuxUp);
       
   970 	SignalError(aSAP, KErrRfcommSAPUnexpectedEvent, MSocketNotify::EErrorAllOperations);
       
   971 	}
       
   972 	
       
   973 void TRfcommStateWaitForMux::UA(CRfcommSAP& /*aSAP*/)
       
   974 	{
       
   975 	DebugPanicInState(ERfcommFrameBeforeMuxUp);
       
   976 	/*ignore and hope for the best*/
       
   977 	}
       
   978 
       
   979 void TRfcommStateWaitForMux::DISC(CRfcommSAP& aSAP)
       
   980 	{
       
   981 	DebugPanicInState(ERfcommFrameBeforeMuxUp);
       
   982 	SignalError(aSAP, KErrRfcommSAPUnexpectedEvent, MSocketNotify::EErrorAllOperations);
       
   983 	}
       
   984 
       
   985 void TRfcommStateWaitForMux::DM(CRfcommSAP& /*aSAP*/)
       
   986 	{
       
   987 	DebugPanicInState(ERfcommFrameBeforeMuxUp);
       
   988 	/*ignore and hope for the best*/
       
   989 	}
       
   990 
       
   991 void TRfcommStateWaitForMux::RPN(CRfcommSAP& aSAP, const TRfcommRPNTransaction& /*aRPNTransaction*/, CRfcommMuxer& /*aMux*/, TUint8 /*aDLCI*/)
       
   992 	{
       
   993 	DebugPanicInState(ERfcommFrameBeforeMuxUp);
       
   994 	SignalError(aSAP, KErrRfcommSAPUnexpectedEvent, MSocketNotify::EErrorAllOperations);
       
   995 	}
       
   996 
       
   997 void TRfcommStateWaitForMux::RPNRsp(CRfcommSAP& /*aSAP*/, const TRfcommRPNTransaction& /*aRPNTransaction*/)
       
   998 	{
       
   999 	DebugPanicInState(ERfcommFrameBeforeMuxUp);
       
  1000 	/*ignore and hope for the best*/
       
  1001 	}
       
  1002 
       
  1003 // Parameter negotiation
       
  1004 void TRfcommStateWaitForMux::PN(CRfcommSAP& aSAP, TRfcommPortParams& /*aParams*/, CRfcommMuxer& /*aMux*/, TUint8 /*aDLCI*/)
       
  1005 	{
       
  1006 	DebugPanicInState(ERfcommFrameBeforeMuxUp);
       
  1007 	SignalError(aSAP, KErrRfcommSAPUnexpectedEvent, MSocketNotify::EErrorAllOperations);
       
  1008 	}
       
  1009   
       
  1010 void TRfcommStateWaitForMux::PNResp(CRfcommSAP& /*aSAP*/, TRfcommPortParams& /*aParams*/)
       
  1011 	{
       
  1012 	DebugPanicInState(ERfcommFrameBeforeMuxUp);
       
  1013 	/*ignore and hope for the best*/
       
  1014 	}
       
  1015 
       
  1016 void TRfcommStateWaitForMux::MSC(CRfcommSAP& /*aSAP*/, TUint8 /*aSignals*/)
       
  1017 	{
       
  1018 	DebugPanicInState(ERfcommFrameBeforeMuxUp);
       
  1019 	/*ignore and hope for the best*/
       
  1020 	}
       
  1021 
       
  1022 void TRfcommStateWaitForMux::RLS(CRfcommSAP& /*aSAP*/, TUint8 /*aStatus*/)
       
  1023 	{
       
  1024 	DebugPanicInState(ERfcommFrameBeforeMuxUp);
       
  1025 	/*ignore and hope for the best*/
       
  1026 	}
       
  1027 
       
  1028 void TRfcommStateWaitForMux::NewData(CRfcommSAP& /*aSAP*/, const TDesC8& /*aData*/)
       
  1029 	{
       
  1030 	DebugPanicInState(ERfcommFrameBeforeMuxUp);
       
  1031 	/*ignore and hope for the best*/
       
  1032 	}
       
  1033 
       
  1034 /*****************************************************************
       
  1035 
       
  1036 State Wait for PN Response
       
  1037 
       
  1038 ******************************************************************/
       
  1039 
       
  1040 TRfcommStateWaitForPNResp::TRfcommStateWaitForPNResp(CRfcommStateFactory& aFactory)
       
  1041 	: TRfcommStateConnecting(aFactory)
       
  1042 	{
       
  1043 	STATENAME("WaitForPNResp");
       
  1044 	}
       
  1045 
       
  1046 void TRfcommStateWaitForPNResp::Enter(CRfcommSAP& aSAP)
       
  1047 	/**
       
  1048 	The Mux is up - it's time to initiate Parameter Negotiations
       
  1049 
       
  1050 	Send a PN packet with our preferred parameters.
       
  1051 	**/
       
  1052 	{
       
  1053 	__ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux));
       
  1054 	TRfcommPortParams params;
       
  1055 	params.iMaxFrameSize=aSAP.MaximumMTU();
       
  1056 	params.iInitialCredit = aSAP.iMux->FlowStrategy()->PNFinalOctet();
       
  1057 
       
  1058 	aSAP.SetProxyForRemoteCredit(params.iInitialCredit); // set up our proxy
       
  1059 #ifdef _DEBUG
       
  1060 	aSAP.iProxyForRemoteCreditsSupplied = params.iInitialCredit;
       
  1061 #endif
       
  1062 	aSAP.iMTU=params.iMaxFrameSize;  // Remember the newly calculated MTU
       
  1063 	LOG2(_L("RFCOMM: Sending PN (Calculated MTU %d from frame size %d)"), aSAP.iMTU, aSAP.iMux->GetMaxDataSize());	
       
  1064 	
       
  1065 	TInt error=aSAP.iMux->SendPN(aSAP, params);
       
  1066 
       
  1067 	if(error!=KErrNone)
       
  1068 		{
       
  1069 		//	Error occurred while sending parameter negotiation command
       
  1070 		FailureWhileConnecting(aSAP, error);
       
  1071 		}
       
  1072 	}
       
  1073 
       
  1074 void TRfcommStateWaitForPNResp::PNResp(CRfcommSAP& aSAP, TRfcommPortParams& aParams)
       
  1075 	/**
       
  1076 	We've received a PN response, which may or may not mean our
       
  1077 	datasize has been accepted
       
  1078 
       
  1079 	If everything is OK (ie. the PN response accepts a MTU size
       
  1080 	between 1 and our original maximum MTU), send a SABM and begin
       
  1081 	waiting for a UA.  If things are not OK, we either signal an error
       
  1082 	or inform the socket that we CanClose (depending on whether we
       
  1083 	were trying to disconnect anyway).
       
  1084 
       
  1085 	**/
       
  1086 	{
       
  1087 	__ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux));
       
  1088 	if(aParams.iCreditIndicator == (KCBFCResponseFlag >> 4))
       
  1089 		{
       
  1090 		aSAP.SetInitialLocalCredit(aParams.iInitialCredit);
       
  1091 		#ifdef _DEBUG
       
  1092 		aSAP.iLocalCreditsSupplied = aParams.iInitialCredit;
       
  1093 		#endif
       
  1094 		}
       
  1095 	TInt error=KErrNone;
       
  1096 	if(aParams.iMaxFrameSize<=aSAP.NegotiatedMTU() && aParams.iMaxFrameSize>0)
       
  1097 		{
       
  1098 		LOG1(_L("RFCOMM: Received acceptable PN Response with MTU %d"),aParams.iMaxFrameSize);
       
  1099 		
       
  1100 		// We have an MTU value so ask L2Cap to work out the optimal MTU value based on the one
       
  1101 		// received from the remote. Note that the Max Frame Size is the max data size for Rfcomm
       
  1102 		// so we need to add on the max Rfcomm header size to create the restriction on L2Cap
       
  1103 		// MTU.
       
  1104 		TPckgBuf<TInt> restrictedMtu(aParams.iMaxFrameSize + KMaxFrameOverhead);
       
  1105 		error = aSAP.GetOption(KSolBtL2CAP, KL2CAPOutboundMTUForBestPerformanceWithRestriction, restrictedMtu);
       
  1106 
       
  1107 		// If we get an error continue but with a possible non-optimal MTU value. iMTU is the max
       
  1108 		// data size so remove the max Rfcomm header size as these will get added later.
       
  1109  		aSAP.iMTU = (error == KErrNone) ? restrictedMtu() - KMaxFrameOverhead : aParams.iMaxFrameSize;
       
  1110  		error = KErrNone;
       
  1111  		
       
  1112 		}
       
  1113 	else
       
  1114 		{
       
  1115 		LOG1(_L("RFCOMM: Received unacceptable PN Response with MTU %d"),aParams.iMaxFrameSize);
       
  1116 		error=KErrRfcommParameterNegotiationFailure;
       
  1117 		};
       
  1118 
       
  1119 	if(error!=KErrNone)
       
  1120 		{
       
  1121 		FailureWhileConnecting(aSAP,error);
       
  1122 		}
       
  1123 	else
       
  1124 		{
       
  1125 		ChangeState(aSAP, CRfcommStateFactory::EWaitForOutgoingSecurityCheck);
       
  1126 		}
       
  1127 	}
       
  1128 
       
  1129 /*********************************************************************/
       
  1130 /*
       
  1131 	We've received a good PN configuration response and we're waiting for the connection to complete.
       
  1132 
       
  1133 */
       
  1134 
       
  1135 TRfcommStateWaitForUA::TRfcommStateWaitForUA(CRfcommStateFactory& aFactory)
       
  1136 	: TRfcommStateConnecting(aFactory)
       
  1137 	{
       
  1138 	STATENAME("WaitForUA");
       
  1139 	}
       
  1140 
       
  1141 void TRfcommStateWaitForUA::UA(CRfcommSAP& aSAP)
       
  1142 	/**
       
  1143 	   The SABM command has succeeded.
       
  1144 
       
  1145 	   If there is no close pending we go to open, and
       
  1146 	   also construct the SAPs buffers.  If we need to close, we go to
       
  1147 	   the disconnect state.
       
  1148 	**/
       
  1149 	{
       
  1150 	__ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux));
       
  1151 	if(aSAP.iClosePending)
       
  1152 		{
       
  1153 		ChangeState(aSAP, CRfcommStateFactory::EDisconnect);
       
  1154 		}
       
  1155 	else
       
  1156 		{
       
  1157 		TRAPD(err, 
       
  1158 			  aSAP.iDataBuffer.SetLengthL(aSAP.iMux->FlowStrategy()->DataBufferMultiple()*
       
  1159 										  aSAP.iMTU));
       
  1160 		if(err != KErrNone)
       
  1161 			{
       
  1162 			// Failed to alloc, so fail this connect and error
       
  1163 			SignalError(aSAP, err, MSocketNotify::EErrorConnect);
       
  1164 			ChangeState(aSAP, CRfcommStateFactory::EClosed);
       
  1165 			return;
       
  1166 			}
       
  1167 		
       
  1168 		aSAP.iHighTideMark=KRfcommSAPBufferHighMultiple*(aSAP.iMTU);
       
  1169 		aSAP.iLowTideMark=KRfcommSAPBufferLowMultiple*(aSAP.iMTU);
       
  1170 
       
  1171 		
       
  1172 		ChangeState(aSAP, CRfcommStateFactory::EOpen);
       
  1173 		}
       
  1174 	}
       
  1175 
       
  1176 TBool TRfcommStateWaitForUA::HandleFrameResponseTimeout(CRfcommSAP& aSAP)
       
  1177 	/**
       
  1178 	We've waited too long for a UA to come back to us, so we start disconnecting.
       
  1179 
       
  1180 	We also need to signal 
       
  1181 	**/
       
  1182 	{
       
  1183 	if(!aSAP.iClosePending)
       
  1184 		SignalError(aSAP, KErrTimedOut, MSocketNotify::EErrorConnect);
       
  1185 	
       
  1186 	ChangeState(aSAP, CRfcommStateFactory::EDisconnect);
       
  1187 	return ETrue;
       
  1188 	}
       
  1189 
       
  1190 /******************************************************************/
       
  1191 /*
       
  1192   The Listening state.
       
  1193 
       
  1194   Deals with incoming connection requests
       
  1195 */
       
  1196 
       
  1197 TRfcommStateListening::TRfcommStateListening(CRfcommStateFactory& aFactory)
       
  1198 	: TRfcommStateDefault(aFactory)
       
  1199 	{
       
  1200 	STATENAME("Listening");
       
  1201 	}
       
  1202 
       
  1203 void TRfcommStateListening::Enter(CRfcommSAP& aSAP)
       
  1204 	/**
       
  1205 	The SAP is entering the listening state. The protocol needs to know.
       
  1206 	**/
       
  1207 	{
       
  1208 	aSAP.iProtocol.AddIdleSAP(aSAP);
       
  1209 	aSAP.iProtocol.RemoveBoundSAP(aSAP);
       
  1210 	}
       
  1211 
       
  1212 void TRfcommStateListening::Exit(CRfcommSAP& aSAP)
       
  1213 	{
       
  1214 	aSAP.DeregisterCodService();	// See if there is a Service to remove for CodMan
       
  1215 	aSAP.StopListening();
       
  1216 	}
       
  1217 
       
  1218 void TRfcommStateListening::SABM(CRfcommSAP& aSAP, CRfcommMuxer& aMux, TUint8 aDLCI)
       
  1219 	/**
       
  1220 	A SABM sent to a listening SAP means we need create a clone SAP
       
  1221 	**/
       
  1222 	{
       
  1223 	//	NB. The criteria of the following assert will vary for the different states
       
  1224 	//	that this function gets called in.
       
  1225 	__ASSERT_DEBUG(aDLCI!=0, PanicInState(ERfcommBadDLCIForClone));
       
  1226 	
       
  1227 	CRfcommSAP* newSAP=AttemptToClone(aSAP, aMux, aDLCI);
       
  1228 	if(newSAP) 
       
  1229 		newSAP->SABM(aMux, aDLCI);
       
  1230 	}
       
  1231 
       
  1232 void TRfcommStateListening::PN(CRfcommSAP& aSAP, TRfcommPortParams& aParams, CRfcommMuxer& aMux, TUint8 aDLCI)
       
  1233 	/**
       
  1234 	A PN sent to a listening SAP means we need create a clone SAP
       
  1235 	**/
       
  1236 	{
       
  1237 	//	NB. The criteria of the following assert will vary for the different states
       
  1238 	//	that this function gets called in.
       
  1239 	__ASSERT_DEBUG(aDLCI!=0, PanicInState(ERfcommBadDLCIForClone));
       
  1240 	
       
  1241 	CRfcommSAP* newSAP=AttemptToClone(aSAP, aMux, aDLCI);
       
  1242 	if(newSAP)
       
  1243 		{
       
  1244 		newSAP->PN(aParams, aMux, aDLCI);
       
  1245 		}
       
  1246 	else
       
  1247 		{
       
  1248 		// Uh Oh! Couldn't get a SAP, don't worry too much - a DM has been sent
       
  1249 		LOG(_L("[rfcommstates.cpp]: Couldn't clone a SAP after receiving a PN\n"));
       
  1250 		}
       
  1251 	}
       
  1252 
       
  1253 void TRfcommStateListening::RPN(CRfcommSAP& aSAP, const TRfcommRPNTransaction& aRPNTransaction, CRfcommMuxer& aMux, TUint8 aDLCI)
       
  1254 	/**
       
  1255 	A RPN sent to a listening SAP means we need create a clone SAP
       
  1256 	**/
       
  1257 	{
       
  1258 	__ASSERT_DEBUG(aDLCI!=0, PanicInState(ERfcommBadDLCIForClone));
       
  1259 	
       
  1260 	CRfcommSAP* newSAP=AttemptToClone(aSAP, aMux, aDLCI);
       
  1261 	if(newSAP)
       
  1262 		{
       
  1263 		newSAP->RPN(&aRPNTransaction, aMux, aDLCI);
       
  1264 		}
       
  1265 	else
       
  1266 		{
       
  1267 		// Uh Oh! Couldn't get a SAP, don't worry too much - a DM has been sent
       
  1268 		LOG(_L("[rfcommstates.cpp]: Couldn't clone a SAP after receiving a RPN\n"));
       
  1269 		}
       
  1270 	}
       
  1271 
       
  1272 void TRfcommStateListening::Shutdown(CRfcommSAP& aSAP)
       
  1273 	{
       
  1274 	ChangeState(aSAP, CRfcommStateFactory::EClosed);	
       
  1275 	aSAP.iSocket->CanClose();
       
  1276 	}
       
  1277 
       
  1278 void TRfcommStateListening::FastShutdown(CRfcommSAP& aSAP)
       
  1279 	{
       
  1280 	ChangeState(aSAP, CRfcommStateFactory::EClosed);
       
  1281 	}
       
  1282 
       
  1283 CRfcommSAP* TRfcommStateListening::AttemptToClone(CRfcommSAP& aSAP, CRfcommMuxer& aMux, TUint8 aDLCI)
       
  1284 	/**
       
  1285 	Utility function private to TRfcommStateListening which attempts to create a cloned SAP
       
  1286 
       
  1287 	@param aSAP The SAP to be cloned
       
  1288 	@param aMux The Muxer to attach it to
       
  1289 	@param aDLCI The DLCI of the cloned SAP
       
  1290 	**/
       
  1291 	{
       
  1292 	CRfcommSAP* newSAP=aSAP.CloneMe();
       
  1293 	
       
  1294 	if(!newSAP)
       
  1295 		{
       
  1296 		//	A new clone could not be created - send a DM, game over
       
  1297 		aMux.SendDM(aDLCI);
       
  1298 		}
       
  1299 	else
       
  1300 		{
       
  1301 		//	Set up details of the new identity of the clone
       
  1302 
       
  1303 		//	Put it in WaitForSABM state
       
  1304 		newSAP->iState=iFactory.GetState(CRfcommStateFactory::EWaitForSABM);
       
  1305 		newSAP->iState->Enter(*newSAP);
       
  1306 
       
  1307 		newSAP->iSignals=aSAP.iSignals;
       
  1308 		newSAP->iDLCI=aDLCI;
       
  1309 		newSAP->iServerChannel=aMux.MakeServerChannel(aDLCI);
       
  1310 		newSAP->iRemoteDev=aMux.RemoteBTAddr();
       
  1311 		//  Must come after registering the remote address with the new SAP because we will need 
       
  1312 		//  the remote address  to find a link in LinkMgrProtocol to override LPM on
       
  1313 		newSAP->iProtocol.ControlPlane().ModifyPhysicalLink(EOverrideLPMWithTimeout, newSAP->iRemoteDev);
       
  1314 		newSAP->iUserDefinedMTU=aSAP.iUserDefinedMTU;	//	We take our cues as
       
  1315 														//	regards max MTU from
       
  1316 														//	the listening SAP.
       
  1317 		
       
  1318 		newSAP->iMux=&aMux;
       
  1319 		//	NB. The listening SAP retains ownership of the SAP until it sends a
       
  1320 		//	ConnectComplete up for it.
       
  1321 		aMux.AddSAP(*newSAP);
       
  1322 		}
       
  1323 
       
  1324 	return newSAP;
       
  1325 	}
       
  1326 
       
  1327 TInt TRfcommStateListening::SetOption(CRfcommSAP &aSAP, TUint aLevel, 
       
  1328 								      TUint aName, const TDesC8& aOption)
       
  1329     /**
       
  1330        Allow modem status to be modified whilst we are listening.
       
  1331     **/
       
  1332     {
       
  1333 	if(aLevel == KSolBtRFCOMM && aName == KRFCOMMLocalModemStatus)
       
  1334         {
       
  1335 		if ( aOption.Length() != sizeof(TUint8) )
       
  1336 			{
       
  1337 			return KErrArgument;
       
  1338 			}
       
  1339 		else
       
  1340 			{
       
  1341 			TPckgBuf<TUint8> signals;
       
  1342 			signals.Copy(aOption);
       
  1343 			aSAP.iSignals = signals();
       
  1344 			return KErrNone;
       
  1345 			}
       
  1346         }
       
  1347 
       
  1348     return TRfcommStateDefault::SetOption(aSAP, aLevel, aName, aOption);
       
  1349 	}
       
  1350 
       
  1351 /*****************************************************************/
       
  1352 /*
       
  1353   The cloned base state
       
  1354 */
       
  1355 
       
  1356 TRfcommStateCloned::TRfcommStateCloned(CRfcommStateFactory& aFactory)
       
  1357 	: TRfcommStateDefault(aFactory)
       
  1358 	{
       
  1359 	}
       
  1360 
       
  1361 void TRfcommStateCloned::LinkDown(CRfcommSAP& aSAP)
       
  1362 	{
       
  1363 	aSAP.iParentSAP->ChildConnectFailed(aSAP);
       
  1364 	}
       
  1365 
       
  1366 void TRfcommStateCloned::Error(CRfcommSAP& aSAP, TInt /*aErr*/,
       
  1367 									CRfcommSAP::TErrorTypes /*aType*/)
       
  1368 	{
       
  1369 	aSAP.iParentSAP->ChildConnectFailed(aSAP);	//	Will delete us...
       
  1370 	}
       
  1371 
       
  1372 void TRfcommStateCloned::DISC(CRfcommSAP& aSAP)
       
  1373 	/**
       
  1374 	   DISC, so the other end wants us to go away.
       
  1375 	   
       
  1376 	   Kill ourselves after acknowledging it.
       
  1377 	**/
       
  1378 	{
       
  1379 	aSAP.iMux->SendUA(aSAP.DLCI());		//	Send a UA which will outlive this SAP
       
  1380 	aSAP.iParentSAP->ChildConnectFailed(aSAP);
       
  1381 	}
       
  1382 
       
  1383 void TRfcommStateCloned::DM(CRfcommSAP& aSAP)
       
  1384 	/**
       
  1385 	   We've got a DM in, which means that something's wrong.
       
  1386 
       
  1387 	   We'll junk this connection, since we should not get a DM as we
       
  1388 	   haven't sent any commands.  The other end is obviously very
       
  1389 	   confused.
       
  1390 	**/
       
  1391 	{
       
  1392 	aSAP.iParentSAP->ChildConnectFailed(aSAP);
       
  1393 	}
       
  1394 
       
  1395 /******************************************************************/
       
  1396 /*
       
  1397   The Wait For SABM state.
       
  1398 
       
  1399   (The intial state of a cloned SAP)
       
  1400 */
       
  1401 
       
  1402 TRfcommStateWaitForSABM::TRfcommStateWaitForSABM(CRfcommStateFactory& aFactory)
       
  1403 	: TRfcommStateCloned(aFactory)
       
  1404 	{
       
  1405 	STATENAME("WaitForSABM");
       
  1406 	}
       
  1407 
       
  1408 void TRfcommStateWaitForSABM::SABM(CRfcommSAP& aSAP, CRfcommMuxer& aMux, TUint8 aDLCI)
       
  1409 	/**
       
  1410 	We received a SABM - Tell our parent SAP that we're connected
       
  1411 	**/
       
  1412 	{
       
  1413 	if(aSAP.iMTU==0)	//	i.e. We've not entered into any negotiations...
       
  1414 		aSAP.iMTU=KRfcommDefaultMTU;	//	...so set to default.
       
  1415 
       
  1416 	//	We can set up the Data Buffer since MTU negotiations are now over.
       
  1417 	//TRAPD(err, aSAP.iDataBuffer.SetLengthL(KRfcommSAPBufferMultiple*aSAP.iMTU));
       
  1418 		TRAPD(err, 
       
  1419 			  aSAP.iDataBuffer.SetLengthL(aMux.FlowStrategy()->DataBufferMultiple()*
       
  1420 										  aSAP.iMTU));
       
  1421 	if(err != KErrNone)
       
  1422 		{
       
  1423 		// Failed to alloc, so fail this connect and error
       
  1424 		aMux.SendDM(aDLCI);
       
  1425 		aSAP.iParentSAP->ChildConnectFailed(aSAP);	//	Will delete us...	
       
  1426 		return;
       
  1427 		}
       
  1428 	
       
  1429 	aSAP.iHighTideMark=KRfcommSAPBufferHighMultiple*(aSAP.iMTU);
       
  1430 	aSAP.iLowTideMark=KRfcommSAPBufferLowMultiple*(aSAP.iMTU);
       
  1431 
       
  1432 	ChangeState(aSAP,CRfcommStateFactory::EWaitForIncomingSecurityCheck);
       
  1433 	}
       
  1434 
       
  1435 #ifndef _DEBUG
       
  1436 void TRfcommStateWaitForSABM::PN(CRfcommSAP& aSAP, TRfcommPortParams& aParams, 
       
  1437 								 CRfcommMuxer& /*aMux*/, TUint8 /*aDLCI*/)
       
  1438 #else
       
  1439 void TRfcommStateWaitForSABM::PN(CRfcommSAP& aSAP, TRfcommPortParams& aParams, 
       
  1440 								 CRfcommMuxer& aMux, TUint8 /*aDLCI*/)
       
  1441 #endif
       
  1442 	{
       
  1443 	__ASSERT_DEBUG(aSAP.iMux==&aMux,PanicInState(ERfcommInvalidMuxInSAP));
       
  1444 	if(aSAP.iMTU==0)
       
  1445 		{
       
  1446 		//	We have no MTU set for the SAP at the moment. Try to determine
       
  1447 		//	the upper limit of what we can handle
       
  1448 		aSAP.iMTU=aSAP.MaximumMTU();
       
  1449 		}
       
  1450 		
       
  1451 	if(aParams.iMaxFrameSize>aSAP.iMTU || aParams.iMaxFrameSize<=0)
       
  1452 		{
       
  1453 		//	Either the remote device wants a larger MTU or has provided us
       
  1454 		//	with a nonsensical <=0 one.
       
  1455 		//	Either way, try to negotiate the MTU to our maximum
       
  1456 		aParams.iMaxFrameSize=aSAP.iMTU;
       
  1457 		}
       
  1458 	else
       
  1459 		{
       
  1460 		
       
  1461 		// We have an MTU value so ask L2Cap to work out the optimal MTU value based on the one
       
  1462 		// received from the remote. Note that the Max Frame Size is the max data size for Rfcomm
       
  1463 		// so we need to add on the max Rfcomm header size to create the restriction on L2Cap
       
  1464 		// MTU.
       
  1465 		TPckgBuf<TInt> restrictedMtu(aParams.iMaxFrameSize + KMaxFrameOverhead);
       
  1466 		TInt err = aSAP.GetOption(KSolBtL2CAP, KL2CAPOutboundMTUForBestPerformanceWithRestriction, restrictedMtu);
       
  1467 
       
  1468 		
       
  1469 		// If we get an error continue but with a possible non-optimal MTU value. iMTU is the max
       
  1470 		// data size so remove the max Rfcomm header size as these will get added later.
       
  1471  		aSAP.iMTU = (err == KErrNone) ? restrictedMtu() - KMaxFrameOverhead : aParams.iMaxFrameSize;
       
  1472  		}	
       
  1473 
       
  1474 	if(aParams.iCreditIndicator == (KCBFCCommandFlag >> 4))
       
  1475 		{
       
  1476 		// Remote device is using CBFC. Set up the credit counts
       
  1477 		aSAP.SetInitialLocalCredit(aParams.iInitialCredit); // Credits we've just been given
       
  1478 		
       
  1479 		 // now set to the credits we will give them
       
  1480 		aParams.iInitialCredit = aSAP.iMux->FlowStrategy()->PNFinalOctet();
       
  1481 		aSAP.SetProxyForRemoteCredit(aParams.iInitialCredit); // and record it
       
  1482 		}
       
  1483 
       
  1484 	aSAP.iMux->SendPNResponse(aSAP, aParams);
       
  1485 	}
       
  1486 
       
  1487 void TRfcommStateWaitForSABM::RPN(CRfcommSAP& aSAP, const TRfcommRPNTransaction& aRPNTransaction, 
       
  1488 								 CRfcommMuxer& /*aMux*/, TUint8 /*aDLCI*/)
       
  1489 	{
       
  1490 	// Write whatever's changed into our local port params. 
       
  1491 	aSAP.iLocalPortParams.UpdateFromRPNTransaction(aRPNTransaction);
       
  1492 	
       
  1493 	// Send L2CAP exactly what they sent us, except this is a response
       
  1494 	aSAP.iMux->SendRPN(aSAP, EFalse, KRPNResponseLength, aRPNTransaction);
       
  1495 
       
  1496 	// Don't bother telling the user. If they're interested they'll just have
       
  1497 	// to keep doing getOpts whenever they feel like it!
       
  1498 	}
       
  1499 
       
  1500 void TRfcommStateWaitForSABM::MuxUp(CRfcommSAP& /*aSAP*/)
       
  1501 	{
       
  1502 	//	Do nothing - included because the default class will panic.
       
  1503 	}
       
  1504 
       
  1505 
       
  1506 /******************************************************************/
       
  1507 /*
       
  1508   The Incoming Security Check state.
       
  1509 
       
  1510   Handles making and responding to a security check on the security manager.
       
  1511 
       
  1512 */
       
  1513 
       
  1514 TRfcommStateIncomingSecurityCheck::TRfcommStateIncomingSecurityCheck(CRfcommStateFactory& aFactory)
       
  1515 	: TRfcommStateCloned(aFactory)
       
  1516 	{
       
  1517 	STATENAME("IncomingSecurityCheck");
       
  1518 	}
       
  1519 
       
  1520 void TRfcommStateIncomingSecurityCheck::Enter(CRfcommSAP& aSAP)
       
  1521 	{
       
  1522 	// INCOMING security
       
  1523 	// The listening SAP has the security settings, and possible device overrides
       
  1524 	aSAP.StartAccessRequest(aSAP.ListeningSAP());
       
  1525 	}
       
  1526 
       
  1527 void TRfcommStateIncomingSecurityCheck::AccessRequestComplete(CRfcommSAP& aSAP, TInt aResult)
       
  1528 	{
       
  1529 	if(aResult==KErrNone)
       
  1530 		{
       
  1531 		LOG1(_L("RFCOMM: Access Request Successful (DLCI %d)"), aSAP.DLCI());
       
  1532 		ChangeState(aSAP, CRfcommStateFactory::EWaitForStart);
       
  1533 		}
       
  1534 	else
       
  1535 		{//	Something is not well - inform our parent.
       
  1536 		// This will result in us being deleted, so send DM for the DLCI
       
  1537 		LOG2(_L("RFCOMM: Access Request Failed (DLCI %d, Error %d)"), aSAP.DLCI(),aResult);
       
  1538 		aSAP.iMux->SendDM(aSAP.DLCI());
       
  1539 		aSAP.iParentSAP->ChildConnectFailed(aSAP);
       
  1540 		}
       
  1541 	}
       
  1542 
       
  1543 void TRfcommStateIncomingSecurityCheck::Exit(CRfcommSAP& aSAP)
       
  1544 	{
       
  1545 	 aSAP.CancelAccessRequest(); 
       
  1546 	}
       
  1547 
       
  1548 /******************************************************************/
       
  1549 /*
       
  1550   The Outgoing Security Check state.
       
  1551 
       
  1552   Handles making and responding to a security check on the security manager.
       
  1553 
       
  1554 */
       
  1555 
       
  1556 TRfcommStateOutgoingSecurityCheck::TRfcommStateOutgoingSecurityCheck(CRfcommStateFactory& aFactory)
       
  1557 	: TRfcommStateConnecting(aFactory)
       
  1558 	{
       
  1559 	STATENAME("OutgoingSecurityCheck");
       
  1560 	}
       
  1561 
       
  1562 void TRfcommStateOutgoingSecurityCheck::Enter(CRfcommSAP& aSAP)
       
  1563 	{
       
  1564 	// Outgoing security
       
  1565 	// The listening SAP has the security settings, and possible device overrides
       
  1566 	aSAP.StartAccessRequest(aSAP);
       
  1567 	}
       
  1568 
       
  1569 void TRfcommStateOutgoingSecurityCheck::AccessRequestComplete(CRfcommSAP& aSAP, TInt aResult)
       
  1570 	{
       
  1571 	if(aResult==EBTSecManAccessGranted)
       
  1572 		{
       
  1573 		LOG1(_L("RFCOMM: Access Request Successful (DLCI %d)"), aSAP.DLCI());
       
  1574 		aResult = aSAP.iMux->SendSABM(aSAP);
       
  1575 		}
       
  1576 
       
  1577 	if (aResult < KErrNone || aResult == EBTSecManAccessDenied)
       
  1578 		{//	Something is not well - inform our parent.
       
  1579 		// This will result in us being deleted, so send DM for the DLCI
       
  1580 		LOG2(_L("RFCOMM: Outgoing security Failed (DLCI %d, Error %d)"), aSAP.DLCI(),aResult);
       
  1581 		FailureWhileConnecting(aSAP, KErrCouldNotConnect);
       
  1582 		}
       
  1583 	else
       
  1584 		{
       
  1585 		ChangeState(aSAP, CRfcommStateFactory::EWaitForUA);
       
  1586 		}
       
  1587 	}
       
  1588 
       
  1589 void TRfcommStateOutgoingSecurityCheck::Exit(CRfcommSAP& aSAP)
       
  1590 	{
       
  1591 	aSAP.CancelAccessRequest(); 
       
  1592 	}
       
  1593 
       
  1594 
       
  1595 /******************************************************************/
       
  1596 /*
       
  1597   The Wait For Start state.
       
  1598 
       
  1599 */
       
  1600 
       
  1601 TRfcommStateWaitForStart::TRfcommStateWaitForStart(CRfcommStateFactory& aFactory)
       
  1602 	: TRfcommStateDefault(aFactory)
       
  1603 	{
       
  1604 	STATENAME("WaitForStart");
       
  1605 	}
       
  1606 
       
  1607 void TRfcommStateWaitForStart::Enter(CRfcommSAP &aSAP)
       
  1608 	{
       
  1609 	//	NB. The following line effectively passes ownership of aSAP away from
       
  1610 	//	the parent SAP to ESOCK
       
  1611 	aSAP.iParentSAP->ChildConnected(aSAP);
       
  1612 	}
       
  1613 
       
  1614 void TRfcommStateWaitForStart::Start(CRfcommSAP& aSAP)
       
  1615 	/**
       
  1616 	Start has been called on us. Move to the open state.
       
  1617 	**/
       
  1618 	{
       
  1619 	__ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux));
       
  1620 	if(aSAP.iParentSAP!=NULL)
       
  1621 		{
       
  1622 		//	We still have an extant parent listening SAP.
       
  1623 		//	Let them know that we have been started so that they can
       
  1624 		//	accept more cloned SAPs into the WaitForStart state.
       
  1625 		aSAP.iParentSAP->ChildStarted(aSAP);
       
  1626 		}
       
  1627 	aSAP.iMux->SendUA(aSAP);
       
  1628 
       
  1629 	ChangeState(aSAP, CRfcommStateFactory::EOpen);
       
  1630 	}
       
  1631 
       
  1632 void TRfcommStateWaitForStart::DISC(CRfcommSAP& aSAP)
       
  1633 	/**
       
  1634 	We are waiting for a Start, but the remote device has decided to disconnect us.
       
  1635 
       
  1636 	Send a UA, and enter the CloseOnStart state.
       
  1637 	**/
       
  1638 	{
       
  1639 	__ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux));
       
  1640 	aSAP.iMux->SendUA(aSAP.DLCI());
       
  1641 	aSAP.iMux->DetachSAP(aSAP);		//	Because we're just waiting about for a Start
       
  1642 									//	from above - we're not interested in what is
       
  1643 									//	coming in from below (esp. LinkDown notification).
       
  1644 	ChangeState(aSAP,CRfcommStateFactory::ECloseOnStart);
       
  1645 	}
       
  1646 
       
  1647 void TRfcommStateWaitForStart::Error(CRfcommSAP& aSAP, TInt /*aErr*/,
       
  1648 								   CRfcommSAP::TErrorTypes /*aType*/)
       
  1649 	{
       
  1650 	//	We can't really do anything at this point with an error,
       
  1651 	//	because ESOCK knows about us. Therefore, the best we can
       
  1652 	//	do is to move into CloseOnStart state.
       
  1653 	ChangeState(aSAP,CRfcommStateFactory::ECloseOnStart);
       
  1654 	}
       
  1655 
       
  1656 /******************************************************************/
       
  1657 /*
       
  1658   The Close On Start state.
       
  1659 
       
  1660   For when a SAP triggers a ConnectComplete, but receives a remote DISC
       
  1661   before it receives a local Start.
       
  1662 */
       
  1663 
       
  1664 TRfcommStateCloseOnStart::TRfcommStateCloseOnStart(CRfcommStateFactory& aFactory)
       
  1665 	: TRfcommStateDefault(aFactory)
       
  1666 	{
       
  1667 	STATENAME("CloseOnStart");
       
  1668 	}
       
  1669 
       
  1670 void TRfcommStateCloseOnStart::Start(CRfcommSAP& aSAP)
       
  1671 	{
       
  1672 	//	NB. The Disconnect() invalidates the cloned SAP on ESOCKs
       
  1673 	//	accept queue - however, a client side Accept() will still be
       
  1674 	//	completed with KErrNone. The first read or write will be
       
  1675 	//	completed with KErrDisconnected.
       
  1676 	//
       
  1677 	aSAP.iSocket->Disconnect();
       
  1678 
       
  1679 	if(aSAP.iParentSAP!=NULL)
       
  1680 		{
       
  1681 		//	We still have an extant parent listening SAP.
       
  1682 		//	Let them know that we have been started so that they can
       
  1683 		//	accept more cloned SAPs into the WaitForStart state.
       
  1684 		aSAP.iParentSAP->ChildStarted(aSAP);
       
  1685 		}
       
  1686 
       
  1687 	ChangeState(aSAP, CRfcommStateFactory::EClosed);
       
  1688 	}
       
  1689 
       
  1690 void TRfcommStateCloseOnStart::Error(CRfcommSAP& /*aSAP*/, TInt /*aErr*/,
       
  1691 									   CRfcommSAP::TErrorTypes /*aType*/)
       
  1692 	{
       
  1693 	//	Nothing we can really do with this error, since we're already
       
  1694 	//	going to close on start.
       
  1695 	}
       
  1696 
       
  1697 
       
  1698 /******************************************************************/
       
  1699 /*
       
  1700   The open state.
       
  1701 
       
  1702   Here all the data xfer and flow control is handled.
       
  1703 */
       
  1704 
       
  1705 TRfcommStateOpen::TRfcommStateOpen(CRfcommStateFactory& aFactory)
       
  1706 	: TRfcommStateDefault(aFactory)
       
  1707 	{
       
  1708 	STATENAME("Open");
       
  1709 	}
       
  1710 
       
  1711 void TRfcommStateOpen::Enter(CRfcommSAP& aSAP)
       
  1712 	/**
       
  1713 	   We've entered the open state, so tell the SAP.
       
  1714 	**/
       
  1715 	{
       
  1716 	// If this fails what happens?
       
  1717 	TInt err=aSAP.iMux->SendMSC(aSAP, aSAP.iSignals);
       
  1718 	if(err != KErrNone)
       
  1719 		{
       
  1720 		// Failed to alloc, so fail this connect and error
       
  1721 		SignalError(aSAP, err, MSocketNotify::EErrorConnect);
       
  1722 		ChangeState(aSAP, CRfcommStateFactory::EClosed);
       
  1723 		return;
       
  1724 		}
       
  1725 	
       
  1726 	aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EUndoOverridePark, aSAP.iRemoteDev);
       
  1727 	aSAP.iSocket->ConnectComplete();
       
  1728 	aSAP.CTS(EFalse);			//	So that we block should anyone try to write
       
  1729 								//	anything through this SAP before we get MSC
       
  1730 								//	from remote side.
       
  1731 	aSAP.iReceivedMSC=EFalse;	//	Until we receive an MSC, we consider any 
       
  1732 								//	user data we receive as being a bit naughty
       
  1733 								//	(other device is non 7.10 compliant)
       
  1734 	}
       
  1735 
       
  1736 void TRfcommStateOpen::PerformDataAwareStateChange(CRfcommSAP& aSAP)
       
  1737 	{
       
  1738 	if(aSAP.iNewDataToNotify)
       
  1739 		{
       
  1740 		// We have outstanding data, so move to a half-closed state
       
  1741 		// where stuff can be read out but not sent
       
  1742 		ChangeState(aSAP, CRfcommStateFactory::EDisconnecting);
       
  1743 		}
       
  1744 	else
       
  1745 		{
       
  1746 		// Now call DisConnect().  Eventually this sap will be cleared up.
       
  1747 		ChangeState(aSAP, CRfcommStateFactory::EClosed);
       
  1748 		aSAP.iSocket->Disconnect();
       
  1749 		}
       
  1750 	}
       
  1751 
       
  1752 
       
  1753 void TRfcommStateOpen::Exit(CRfcommSAP& aSAP)
       
  1754 	/**
       
  1755 	   Exit the open channel
       
  1756 	**/
       
  1757 	{
       
  1758 	aSAP.DeregisterCodService();	// See if there is a Service to remove for CodMan
       
  1759 	}
       
  1760 
       
  1761 
       
  1762 void TRfcommStateOpen::Shutdown(CRfcommSAP& aSAP)
       
  1763 	/**
       
  1764 	   Shutdown the open channel gracefully
       
  1765 	**/
       
  1766 	{
       
  1767 	aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EOverridePark, aSAP.iRemoteDev);
       
  1768 	aSAP.iClosePending=ETrue;
       
  1769 	ChangeState(aSAP, CRfcommStateFactory::EDisconnect);
       
  1770 	}
       
  1771 
       
  1772 void TRfcommStateOpen::FastShutdown(CRfcommSAP& aSAP)
       
  1773 	/**
       
  1774 	   Terminate the session with extreme prejudice :-)
       
  1775 
       
  1776 	   Send a disconnect, but don't bother to wait around since we'll
       
  1777 	   be deleted by our owner when this call returns.
       
  1778 	**/
       
  1779 	{
       
  1780 	//	Send a DISC using the DLCI based overload which ensures that
       
  1781 	//	the queued DISC frame does not get deleted when the SAP gets 
       
  1782 	//	removed from the muxer
       
  1783 	__ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux));
       
  1784 	aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EOverridePark, aSAP.iRemoteDev);
       
  1785 	aSAP.iMux->SendDISC(aSAP.DLCI());  // Disassociated from the SAP
       
  1786 	ChangeState(aSAP, CRfcommStateFactory::EClosed);
       
  1787 	}
       
  1788 
       
  1789 TInt TRfcommStateOpen::Send(CRfcommSAP& aSAP, const TDesC8& aData)
       
  1790 	/**
       
  1791 	   Attempt to send some data.
       
  1792 	   
       
  1793 	   We fragment the data and issue writes to the mux.  Keep going
       
  1794 	   until either the mux tells us to back off, or until all the
       
  1795 	   data has been sent.
       
  1796 	   
       
  1797 	   We also obey our flow control setting, so we only send if we
       
  1798 	   are clear to send
       
  1799 	   
       
  1800 	   Note that when we fail to send all the data, ESOCK will keep
       
  1801 	   calling us until we return zero before marking us as blocked.
       
  1802 	   Therefore we have to check if we're blocked before trying to
       
  1803 	   send anything.
       
  1804 	   
       
  1805        @return Length of data actually sent
       
  1806 	**/
       
  1807 	{
       
  1808 	__ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux));
       
  1809 	
       
  1810 	TInt len=0; // Current amount we've sent.
       
  1811 	TInt fraglen;
       
  1812 	TInt sentlen=0;
       
  1813 	
       
  1814 	if(!aSAP.SendBlocked())
       
  1815 		{
       
  1816 		if(aSAP.CTS()) //FIXME???? make general to accommodate CBFC as well
       
  1817 			{
       
  1818 			while(len < aData.Length())
       
  1819 				{
       
  1820 				//NB1 0 if !CBFC
       
  1821 				//NB2 A successful 'Write' will update this value for next loop.
       
  1822 				TUint8 credit = aSAP.Mux()->FlowStrategy()->WriteCredit(aSAP); 
       
  1823 				fraglen=Min(aData.Length()-len, STATIC_CAST(TInt, aSAP.UsableMTU(credit)));
       
  1824 				if(aSAP.iMux->FlowStrategy()->AllowWrite(aSAP))
       
  1825 					sentlen=aSAP.iMux->Write(aSAP, credit, aData.Mid(len,fraglen));
       
  1826 				else
       
  1827 					sentlen=0;
       
  1828 				len+=sentlen;
       
  1829 				if(sentlen != fraglen)
       
  1830 					{
       
  1831 					// We failed to send all the data we wanted to, so
       
  1832 					// we're now blocked from sending, and must wait for a
       
  1833 					// notification that we can send again.
       
  1834 					aSAP.SendBlocked(aSAP.SendBlocked() | CRfcommSAP::EBlockedByMux);
       
  1835 					break;
       
  1836 					}
       
  1837 				}
       
  1838 			}
       
  1839 		else
       
  1840 			{
       
  1841 			// We're not clear to send to the other end, so back off ESOCK
       
  1842 			aSAP.SendBlocked(aSAP.SendBlocked() | CRfcommSAP::EBlockedByRemote);
       
  1843 			}
       
  1844 		}
       
  1845 	return len;
       
  1846 	}
       
  1847 
       
  1848 void TRfcommStateOpen::Read(CRfcommSAP& aSAP, TDesC8& aData)
       
  1849 	/**
       
  1850 	   Read some data.
       
  1851 	   
       
  1852 	   This is filled from the circular buffer of incoming data.
       
  1853 	**/
       
  1854 	{
       
  1855 	__ASSERT_DEBUG(aSAP.DataBuffer().Count() >= aData.Length(),
       
  1856 				   PanicInState(ERfcommReadForTooMuchData));
       
  1857 	__ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux));
       
  1858 	LOG1(_L("RFCOMM: Read of %d bytes"), aData.Length());
       
  1859 	
       
  1860 	aSAP.DataBuffer().Remove(const_cast<TUint8*>(aData.Ptr()), aData.Length());
       
  1861 	//TRY_CBFC
       
  1862 	aSAP.iMux->FlowStrategy()->UpdateRxFlowControlState(aSAP);
       
  1863 	//FIXED_ME removed flow control code to flow strategy
       
  1864 	}
       
  1865 
       
  1866 void TRfcommStateOpen::NewData(CRfcommSAP& aSAP, const TDesC8& aData)
       
  1867 	/**
       
  1868 	   New data has come in.
       
  1869 
       
  1870 	   Store it in a buffer, and signal the socket to get it.
       
  1871 	**/
       
  1872 	{
       
  1873 	LOG1(_L("RFCOMM: New data length %d"), aData.Length());
       
  1874 	__ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux));
       
  1875 	__ASSERT_DEBUG(aData.Length() <= aSAP.iMux->GetMaxDataSize(), PanicInState(ERfcommDataPacketTooLong));
       
  1876 
       
  1877 	if(!aSAP.iReceivedMSC)
       
  1878 		{
       
  1879 		//	We're dealing with a rather naughty non-7.10-compliant
       
  1880 		//	RFCOMM implementation which doesn't send an MSC before
       
  1881 		//	sending it's data. Note this fact and continue.
       
  1882 		LOG(_L("RFCOMM: Warning received data before MSC on new connection!"));
       
  1883 		}
       
  1884 	//TRY_CBFC
       
  1885 	if (!aSAP.iMux->FlowStrategy()->NewDataReviseCredits(aSAP, aData)) // ...the remote has overflowed us...
       
  1886 		{
       
  1887 		// remote is ignoring flow control decide whether to disconnect or drop packets (if using CBFC)
       
  1888 		if (aSAP.iMux->FlowStrategy()->FlowType() == CRfcommFlowStrategyFactory::EFlowCreditBased &&
       
  1889 			aSAP.iForgiveCBFCOverflow)
       
  1890 			{
       
  1891 			//drop packet - l2cap frees the underlying packet storage
       
  1892 			return;
       
  1893 			}
       
  1894 		else
       
  1895 			{				
       
  1896 			aSAP.iSocket->Disconnect();
       
  1897 			ChangeState(aSAP, CRfcommStateFactory::EClosed);
       
  1898 			return;
       
  1899 			}
       
  1900 		}
       
  1901 	
       
  1902 	TInt storelen=aSAP.DataBuffer().Add(aData.Ptr(), aData.Length());
       
  1903 	if(storelen != aData.Length())
       
  1904 		{
       
  1905 		// We've not got room for some of the data
       
  1906 		LOG(_L("RFCOMM: Warning received data loss"));
       
  1907 		}
       
  1908 
       
  1909 	// Check to see if we need to quench the source
       
  1910 	LOG1(_L("RFCOMM: Data buffer level %d"), aSAP.DataBuffer().Count());
       
  1911 
       
  1912 	aSAP.iMux->FlowStrategy()->NewData(aSAP);
       
  1913 	//FIXED-ME flow code block removed to strategy object (applies non CBFC flow only).
       
  1914 
       
  1915 	if(storelen)
       
  1916 		{
       
  1917 		aSAP.iNewDataToNotify += storelen;
       
  1918 		aSAP.iNotifyNewDataCallback->CallBack();
       
  1919 		}
       
  1920 	}
       
  1921 
       
  1922 void TRfcommStateOpen::NotifyNewDataCallback(CRfcommSAP& aSAP)
       
  1923 	{
       
  1924 	TInt newData = aSAP.iNewDataToNotify;
       
  1925 	if (newData)
       
  1926 		{
       
  1927 		aSAP.iNewDataToNotify = 0;
       
  1928 		LOG1(_L("RFCOMM: Actually telling Socket of newdata %d bytes"), newData);
       
  1929 		aSAP.iSocket->NewData(newData);
       
  1930 		}
       
  1931 	aSAP.iMux->FlowStrategy()->UpdateRxFlowControlState(aSAP);
       
  1932 	}
       
  1933 
       
  1934 void TRfcommStateOpen::CanSend(CRfcommSAP& aSAP)
       
  1935 	/**
       
  1936 	   SAP is now clear to try to send data again (maybe) since these
       
  1937 	   can be sent any time.
       
  1938 	   
       
  1939 	   Notify the socket.
       
  1940 	**/
       
  1941 	{	
       
  1942 
       
  1943 	__ASSERT_DEBUG(aSAP.SendBlocked() & CRfcommSAP::EBlockedByMux, PanicInState(ERfcommUnexpectedCanSend));
       
  1944 	
       
  1945 	aSAP.SendBlocked(aSAP.SendBlocked() & ~CRfcommSAP::EBlockedByMux);
       
  1946 	aSAP.iSocket->CanSend();
       
  1947 	}
       
  1948 
       
  1949 void TRfcommStateOpen::MSC(CRfcommSAP& aSAP, TUint8 aSignals)
       
  1950 /**	
       
  1951 	Modem signals received from the remote end.
       
  1952 	The only bit we're really interested in is the FC bit but we store
       
  1953 	the rest anyway in case anyone above wants to read it (see GetOpt)
       
  1954 **/
       
  1955 	{
       
  1956 	aSAP.iRemoteModemStatus = aSignals;
       
  1957 
       
  1958 	aSAP.iReceivedMSC=ETrue;
       
  1959 
       
  1960 	//FC
       
  1961 	if(aSAP.iMux->FlowStrategy()->MSC(aSAP, aSignals))
       
  1962 		{
       
  1963 		aSAP.SendBlocked(aSAP.SendBlocked() & ~CRfcommSAP::EBlockedByRemote);
       
  1964 		aSAP.iSocket->CanSend();
       
  1965 		}
       
  1966 	//
       
  1967 
       
  1968 	// Indication of config change
       
  1969 	IoctlComplete(aSAP, KErrNone, KSolBtRFCOMM, KRFCOMMConfigChangeIndicationIoctl, NULL);
       
  1970 
       
  1971 	// If there has been a signal status to watch for set, and this is it, then we send a disconnect error to the client reader
       
  1972 	if(aSAP.iDisconnectMSCSignal && aSAP.iDisconnectMSCSignal == aSignals)
       
  1973 		{
       
  1974 		SignalError(aSAP, KErrDisconnected, MSocketNotify::EErrorRecv);
       
  1975 		}
       
  1976 	}
       
  1977 
       
  1978 void TRfcommStateOpen::RLS(CRfcommSAP& aSAP, TUint8 aStatus)
       
  1979 //	Remote Line Status command received from remote end
       
  1980 //	Just set the SAP's local copy
       
  1981 	{
       
  1982 	aSAP.iRLSstatus = aStatus;
       
  1983 	// Indication of config change
       
  1984 	IoctlComplete(aSAP, KErrNone, KSolBtRFCOMM, KRFCOMMConfigChangeIndicationIoctl, NULL);
       
  1985 	}
       
  1986 
       
  1987 
       
  1988 void TRfcommStateOpen::DISC(CRfcommSAP& aSAP)
       
  1989 	/**
       
  1990 	   The remote end has sent a DISC.  We need to respond.
       
  1991 
       
  1992 	   Q: What do we do about any data in our buffers?
       
  1993 	   A: Q the UA in order, so that all data in our buffers is
       
  1994 	   flushed before the UA is sent.
       
  1995 	**/
       
  1996 	{
       
  1997 	//	Use the DLCI based overload of SendUA, which ensures that the queued
       
  1998 	//	frame has no SAP set.
       
  1999 	//	This ensures that the frame does not get deleted when this SAP is detached
       
  2000 	//	from the muxer, when we enter the Closed state.
       
  2001 	__ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux));
       
  2002 	aSAP.iMux->SendUA(aSAP.DLCI());   // If this fails  there's not much we can do
       
  2003 	PerformDataAwareStateChange(aSAP);
       
  2004 	}
       
  2005 
       
  2006 
       
  2007 void TRfcommStateOpen::DM(CRfcommSAP& aSAP)
       
  2008 	/**
       
  2009 	   A DM, which means the other end has gone away.
       
  2010 
       
  2011 	   Time to error everything.
       
  2012 	**/
       
  2013 	{
       
  2014 	SignalError(aSAP, KErrDisconnected, MSocketNotify::EErrorAllOperations);
       
  2015 	}
       
  2016 
       
  2017 void TRfcommStateOpen::RPN(CRfcommSAP& aSAP, const TRfcommRPNTransaction& aRPNTransaction, CRfcommMuxer& /*aMuxer*/, TUint8 /*aDLCI*/)
       
  2018 //	The remote end has sent us an RPN negotiate command
       
  2019 //	Just accept whatever they suggested then tell them we've accepted
       
  2020 	{
       
  2021 	// Write whatever's changed into our local port params. 
       
  2022 	aSAP.iLocalPortParams.UpdateFromRPNTransaction(aRPNTransaction);
       
  2023 	
       
  2024 	// Send L2CAP exactly what they sent us, except this is a response
       
  2025 	aSAP.iMux->SendRPN(aSAP, EFalse, KRPNResponseLength, aRPNTransaction);
       
  2026 
       
  2027 	// Indication of config change
       
  2028 	IoctlComplete(aSAP, KErrNone, KSolBtRFCOMM, KRFCOMMConfigChangeIndicationIoctl, NULL);
       
  2029 	}
       
  2030 
       
  2031 void TRfcommStateOpen::RPNRsp(CRfcommSAP& aSAP, 
       
  2032 							  const TRfcommRPNTransaction& aRPNTransaction)
       
  2033 //	The remote end has sent us an RPN response
       
  2034 	{
       
  2035 	// Make sure this is the response we are waiting for
       
  2036 	switch(aSAP.iIoctlName)
       
  2037 		{
       
  2038 		case KRFCOMMRemotePortNegCmdIoctl:
       
  2039 			LOG1(_L("RFCOMM: Received Negotiation response for sap %08x"), &aSAP);		
       
  2040 			// Update the local port parameters with what was agreed by the remote end. 
       
  2041 			aSAP.iLocalPortParams.UpdateFromRPNTransaction(aRPNTransaction);
       
  2042 			break;
       
  2043 		case KRFCOMMRemotePortNegRequestIoctl:
       
  2044 			LOG1(_L("RFCOMM: Received Query response for sap %08x"), &aSAP);
       
  2045 			break;
       
  2046 		default:
       
  2047 			__DEBUGGER();
       
  2048 			LOG(_L("Unexpected RPN response\n"));
       
  2049 			return;
       
  2050 		}
       
  2051 
       
  2052 	// Convert the RPN transaction structure into a descriptor
       
  2053 	TPckgC<TRfcommRPNTransaction> RPNTransaction(aRPNTransaction);
       
  2054 	
       
  2055 	// Send the package up to the user			
       
  2056 	IoctlComplete(aSAP, KErrNone, KSolBtRFCOMM, aSAP.iIoctlName, &RPNTransaction);
       
  2057 	}
       
  2058 
       
  2059 void TRfcommStateOpen::PN(CRfcommSAP& aSAP, TRfcommPortParams& /*aParams*/, CRfcommMuxer& /*aMux*/, TUint8 /*aDLCI*/)
       
  2060 	/**
       
  2061 	We received a PN in the open state - no problem, but for simplicity
       
  2062 	we just respond with our current settings (i.e. MTU).
       
  2063 	NB. Importantly, the initial credit field should be set to 0...
       
  2064 	**/
       
  2065 	{
       
  2066 	TRfcommPortParams params;
       
  2067 	params.iMaxFrameSize=aSAP.NegotiatedMTU();
       
  2068 	params.iInitialCredit=0;	//	See F:1 5.5.3 Core spec 1.1
       
  2069 	aSAP.iMux->SendPNResponse(aSAP, params);
       
  2070 	}
       
  2071 
       
  2072 void TRfcommStateOpen::LinkDown(CRfcommSAP& aSAP)
       
  2073 	/**
       
  2074 	   The link has gone down, which means our Mux will be deleting itself.
       
  2075 
       
  2076 	   Go to closed state, which removes us from the mux
       
  2077 	**/
       
  2078 	{
       
  2079 	PerformDataAwareStateChange(aSAP);
       
  2080 	}
       
  2081 
       
  2082 
       
  2083 void TRfcommStateOpen::Ioctl(CRfcommSAP& aSAP,TUint aLevel,TUint aName,TDes8* aOption)
       
  2084 	/**
       
  2085 	   Perform an RFCOMM ioctl that applies to an RFCOMM connection.
       
  2086 
       
  2087 		If it is not valid, an error occurs.
       
  2088 	**/
       
  2089 	{
       
  2090 	TInt ret = KErrNone;
       
  2091 
       
  2092 	switch(aName)
       
  2093 		{
       
  2094 		case KRFCOMMModemStatusCmdIoctl:
       
  2095 			{
       
  2096 			// aOption stores modem status
       
  2097 			if(!aOption)
       
  2098 				{
       
  2099 				ret=KErrArgument;
       
  2100 				}
       
  2101 			else	
       
  2102 				{
       
  2103 				TUint8 flags = TUint8(*aOption->Ptr());
       
  2104 				// Make sure we send our real flow control status, 
       
  2105 				// not just whatever was in the data received from the user
       
  2106 				if(aSAP.CTR())
       
  2107 					{
       
  2108 					flags &= ~KModemSignalFC;		
       
  2109 					}
       
  2110 				else
       
  2111 					{
       
  2112 					flags |= KModemSignalFC;
       
  2113 					}
       
  2114 
       
  2115 				aSAP.SetSignals(flags);
       
  2116 				ret = aSAP.iMux->SendMSC(aSAP, flags);
       
  2117 				}
       
  2118 			}
       
  2119 			// Complete Ioctl with what was sent to us
       
  2120 			IoctlComplete(aSAP, ret, aLevel, aName, aOption);
       
  2121 			break;
       
  2122 
       
  2123 		case KRFCOMMRemoteLineStatusCmdIoctl:
       
  2124 			// aOption stores status of remote line
       
  2125 			ret = aOption ? aSAP.iMux->SendRLS(aSAP, TUint8(*aOption->Ptr())) : KErrArgument;
       
  2126 			// Complete Ioctl with what was sent to us
       
  2127 			IoctlComplete(aSAP, ret, aLevel, aName, aOption);
       
  2128 			break;
       
  2129 
       
  2130 		case KRFCOMMRemotePortNegCmdIoctl:
       
  2131 			LOG1(_L("RFCOMM: Sending RPN negotiate for sap %08x"),
       
  2132 							&aSAP);
       
  2133 			// aOption is really an RPN transaction structure
       
  2134 			ret = aOption ? aSAP.iMux->SendRPN(aSAP, ETrue, KRPNCommandLength, 
       
  2135 				*(TRfcommRPNTransaction*)aOption->Ptr()) : KErrArgument;
       
  2136 			break;
       
  2137 
       
  2138 		case KRFCOMMRemotePortNegRequestIoctl:
       
  2139 			LOG1(_L("RFCOMM: Sending RPN query for sap %08x"), 
       
  2140 							&aSAP);
       
  2141 			// aOption is really an RPN transaction structure
       
  2142 			ret = aOption ? aSAP.iMux->SendRPN(aSAP, ETrue, KRPNRequestLength, 
       
  2143 				*(TRfcommRPNTransaction*)aOption->Ptr()) : KErrArgument;
       
  2144 			break;
       
  2145 
       
  2146 		case KRFCOMMFConIoctl:
       
  2147 			LOG2(_L("RFCOMM: Sending FCon command for device 0x%04x%08x"),
       
  2148 				TUint(TUint16((aSAP.iMux->RemoteBTAddr())[0])),
       
  2149 				TUint((aSAP.iMux->RemoteBTAddr())[2]));
       
  2150 			//FC
       
  2151 			ret=aSAP.iMux->SendFCon();
       
  2152 			//
       
  2153 			IoctlComplete(aSAP, ret, aLevel, aName, aOption);
       
  2154 			break;
       
  2155 			
       
  2156 		case KRFCOMMFCoffIoctl:
       
  2157 			LOG2(_L("RFCOMM: Sending FCoff command for device 0x%04x%08x"),
       
  2158 				TUint(TUint16((aSAP.iMux->RemoteBTAddr())[0])),
       
  2159 				TUint((aSAP.iMux->RemoteBTAddr())[2]));
       
  2160 			//FC
       
  2161 			ret=aSAP.iMux->SendFCoff();
       
  2162 			//
       
  2163 			IoctlComplete(aSAP, ret, aLevel, aName, aOption);
       
  2164 			break;
       
  2165 
       
  2166 		case KRFCOMMConfigChangeIndicationIoctl:
       
  2167 			LOG(_L("RFCOMM: Registering KRFCOMMConfigChangeIndicationIoctl"));
       
  2168 			// Do nothing -- async completion on remote MSC, RPN, RLS
       
  2169 			break;
       
  2170 
       
  2171 		default:
       
  2172 			ret = KErrNotSupported;
       
  2173 		}
       
  2174 
       
  2175 	if(ret != KErrNone)
       
  2176 		{
       
  2177 		aSAP.iIoctlName=0;
       
  2178 		aSAP.iIoctlLevel=0;
       
  2179 		SignalError(aSAP, ret, MSocketNotify::EErrorIoctl);
       
  2180 		}
       
  2181 	}
       
  2182 
       
  2183 void TRfcommStateOpen::IoctlComplete(CRfcommSAP& aSAP, TInt aErr, TUint aLevel,TUint aName, TDesC8* aBuf)
       
  2184 	/**
       
  2185 	   An ioctl has completed.
       
  2186 
       
  2187 	   If it's for us, signal the socket
       
  2188 	**/
       
  2189 	{
       
  2190 	if (aSAP.iIoctlLevel==aLevel &&
       
  2191 		aSAP.iIoctlName ==aName)
       
  2192 		{
       
  2193 		if(aErr == KErrNone)
       
  2194 			{
       
  2195 			aSAP.iSocket->IoctlComplete(aBuf);
       
  2196 			}
       
  2197 		else
       
  2198 			{
       
  2199 			SignalError(aSAP, aErr, MSocketNotify::EErrorIoctl);
       
  2200 			}
       
  2201 		aSAP.iIoctlName=0;
       
  2202 		aSAP.iIoctlLevel=0;
       
  2203 		}
       
  2204 	}
       
  2205 
       
  2206 TInt TRfcommStateOpen::SetOption(CRfcommSAP &aSAP, TUint aLevel, 
       
  2207 								   TUint aName, const TDesC8& aOption)
       
  2208     /**
       
  2209        Allow modem status to be modified whilst open.
       
  2210     **/
       
  2211     {
       
  2212  	TInt ret;
       
  2213     if(aLevel == KSolBtRFCOMM && aName == KRFCOMMLocalModemStatus)
       
  2214 		{
       
  2215 		if ( aOption.Length() != sizeof(TUint8) )
       
  2216 			{
       
  2217 			ret = KErrArgument;
       
  2218 			}
       
  2219 		else
       
  2220 			{
       
  2221 			TUint8 flags = TUint8(*aOption.Ptr());
       
  2222 			if(aSAP.CTR())
       
  2223 				{
       
  2224 				flags &= ~KModemSignalFC;		
       
  2225 				}
       
  2226 			else
       
  2227 				{
       
  2228 				flags |= KModemSignalFC;
       
  2229 				}
       
  2230 
       
  2231 			ret = aSAP.iMux->SendMSC(aSAP, flags);
       
  2232 			if(ret==KErrNone)
       
  2233 				{
       
  2234 				// Oddly, ioctl KRFCOMMModemStatusCmdIoctl updates 
       
  2235 				// local signals regardless of an error sending them
       
  2236 				aSAP.SetSignals(flags);
       
  2237 				}
       
  2238 			}
       
  2239 	 	}
       
  2240  	else
       
  2241  		{
       
  2242  		ret = TRfcommStateDefault::SetOption(aSAP, aLevel, aName, aOption);		
       
  2243  		}
       
  2244    	 	
       
  2245 	 	
       
  2246     return ret;
       
  2247     }
       
  2248 
       
  2249  
       
  2250 //TRY_CBFC
       
  2251 TUint8 TRfcommStateOpen::FreeCredit(CRfcommSAP& aSAP)
       
  2252 	{
       
  2253 	TUint8 creds = aSAP.FreeCreditCalculation();
       
  2254 	return creds;
       
  2255 	}
       
  2256 
       
  2257 TInt TRfcommStateOpen::ProxyForRemoteCredit(const CRfcommSAP& aSAP) const
       
  2258 	{
       
  2259 	return aSAP.iProxyForRemoteCredit;
       
  2260 	}
       
  2261 
       
  2262 TInt TRfcommStateOpen::LocalCredit(const CRfcommSAP& aSAP) const
       
  2263 	{
       
  2264 	return aSAP.iLocalCredit;
       
  2265 	}
       
  2266 
       
  2267 
       
  2268 
       
  2269 /*********************************************************************/
       
  2270 /*
       
  2271   Disconnect state
       
  2272 */
       
  2273 
       
  2274 TRfcommStateDisconnect::TRfcommStateDisconnect(CRfcommStateFactory& aFactory)
       
  2275 	: TRfcommStateDefault(aFactory)
       
  2276 	{
       
  2277 	STATENAME("Disconnect");
       
  2278 	}
       
  2279 
       
  2280 void TRfcommStateDisconnect::Enter(CRfcommSAP& aSAP)
       
  2281 	/**
       
  2282 	   Send out a disconnect via the mux
       
  2283 	**/
       
  2284 	{
       
  2285 	__ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux));
       
  2286 	// Need to kill off any data callback since we don't want it
       
  2287 	aSAP.iNotifyNewDataCallback->Cancel();
       
  2288 	aSAP.iNewDataToNotify = 0;
       
  2289 	aSAP.iDataBuffer.Reset();
       
  2290 	aSAP.iMux->SendDISC(aSAP);
       
  2291 	}
       
  2292 
       
  2293 void TRfcommStateDisconnect::DISC(CRfcommSAP& aSAP)
       
  2294 	/**
       
  2295 	We're attempting to DISC, and apparently so is our peer SAP.
       
  2296 
       
  2297 	Send them a UA, and move to the closed state.
       
  2298 	**/
       
  2299 	{
       
  2300 	aSAP.iMux->SendUA(aSAP.DLCI());	//	Send to DLCI, or we may lose this when the SAP gets deleted.
       
  2301 	DisconnectComplete(aSAP);
       
  2302 	}
       
  2303 
       
  2304 void TRfcommStateDisconnect::UA(CRfcommSAP& aSAP)
       
  2305 	/**
       
  2306 	   An answer to our DISC.
       
  2307 
       
  2308 	   Disconnect from the Mux now, so it can go away if needs be.
       
  2309 	**/
       
  2310 	{
       
  2311 	DisconnectComplete(aSAP);
       
  2312 	}
       
  2313 
       
  2314 void TRfcommStateDisconnect::DM(CRfcommSAP& aSAP)
       
  2315 	/**
       
  2316 	   Strange, the remote end has sent an error for our disconnect.
       
  2317 	   Oh well, better close anyway.
       
  2318 	**/
       
  2319 	{
       
  2320 	DisconnectComplete(aSAP);
       
  2321 	}	
       
  2322 
       
  2323 void TRfcommStateDisconnect::DisconnectComplete(CRfcommSAP& aSAP)
       
  2324 	{
       
  2325 	//	Record whether there is a CanClose pending - entering the closed
       
  2326 	//	state will overwrite this data.
       
  2327 	TBool canCloseRequired=aSAP.iClosePending;
       
  2328 	
       
  2329 	ChangeState(aSAP, CRfcommStateFactory::EClosed);	// Must enter before CanClose, since
       
  2330 														// this may delete us
       
  2331 	if(canCloseRequired)
       
  2332 		aSAP.iSocket->CanClose();
       
  2333 	}
       
  2334 
       
  2335 void TRfcommStateDisconnect::LinkDown(CRfcommSAP& aSAP)
       
  2336 	/**
       
  2337 	The link has gone down during our close.
       
  2338 	**/
       
  2339 	{
       
  2340 	ChangeState(aSAP, CRfcommStateFactory::EClosed);	  // Enter before we get deleted...
       
  2341 	aSAP.iSocket->CanClose();
       
  2342 	}
       
  2343 
       
  2344 /***************************************************************
       
  2345 
       
  2346 The disconnecting state
       
  2347 
       
  2348 ***************************************************************/
       
  2349 
       
  2350 
       
  2351 TRfcommStateDisconnecting::TRfcommStateDisconnecting(CRfcommStateFactory& aFactory)
       
  2352 	: TRfcommStateDefault(aFactory)
       
  2353 	{
       
  2354 	STATENAME("Disconnecting");
       
  2355 	}
       
  2356 
       
  2357 
       
  2358 void TRfcommStateDisconnecting::Enter(CRfcommSAP& aSAP)
       
  2359 	/**
       
  2360 	   Enter the disconnecting state.
       
  2361 
       
  2362 	   This state is entered if we have data for the client, but the
       
  2363 	   other end has disconnected.  Thus we are in a half-disconnected
       
  2364 	   state, where the remote end thinks we're closed and the local
       
  2365 	   end thinks we're open. Since we have data to notify, we'll send
       
  2366 	   it to ESOCK immediately.
       
  2367 
       
  2368 	   We disconnect from the mux as we have no further need for
       
  2369 	   incoming events.
       
  2370 	**/
       
  2371 	{
       
  2372 	__ASSERT_DEBUG(aSAP.iNewDataToNotify, PanicInState(ERfcommStateDisconnectingWithNoData));
       
  2373 	__ASSERT_DEBUG(aSAP.iNotifyNewDataCallback->IsActive(), PanicInState(ERfcommStateDisconnectingWithNoData));
       
  2374 //	aSAP.iNotifyNewDataCallback->Cancel(); // Cancel the outstanding callback
       
  2375 	aSAP.iMux->DetachSAP(aSAP);
       
  2376 	TInt newData = aSAP.iNewDataToNotify;
       
  2377 	if (newData)
       
  2378 		{
       
  2379 		aSAP.iNewDataToNotify = 0;
       
  2380 		aSAP.iSocket->NewData(newData);
       
  2381 		}
       
  2382 	}
       
  2383 
       
  2384 TInt TRfcommStateDisconnecting::Send(CRfcommSAP& aSAP, const TDesC8& /*aData*/)
       
  2385 	/**
       
  2386 	   Attempt to send data, but we can't.
       
  2387 
       
  2388 	   We will signal an error on the send.
       
  2389 	**/
       
  2390 	{
       
  2391 	aSAP.iErrorKicker->SetError(KErrDisconnected, CRfcommSAP::EErrorOperation);  
       
  2392 	aSAP.iErrorKicker->Call(); // FIXME: Note this currently errors everything 
       
  2393 	return 0;
       
  2394 	}
       
  2395 
       
  2396 void TRfcommStateDisconnecting::Read(CRfcommSAP& aSAP, TDesC8& aData)
       
  2397 	/**
       
  2398 	   Read out some of the data from the buffer.
       
  2399 
       
  2400 	   Note that there is no need to deal with flow control, as the
       
  2401 	   link is dead.  Also, there is no need to deal with notifying
       
  2402 	   the mux for more data, since we assume that only data that is
       
  2403 	   notified to us before the DISC is valid.
       
  2404 	**/
       
  2405 	{
       
  2406 	__ASSERT_DEBUG(aSAP.DataBuffer().Count() >= aData.Length(),
       
  2407 				   PanicInState(ERfcommReadForTooMuchData));
       
  2408 	LOG1(_L("RFCOMM: Read of (disconnecting) %d bytes"), aData.Length());
       
  2409 	
       
  2410 	aSAP.DataBuffer().Remove(const_cast<TUint8*>(aData.Ptr()), aData.Length());
       
  2411 	}
       
  2412 
       
  2413 void TRfcommStateDisconnecting::NotifyNewDataCallback(CRfcommSAP& aSAP)
       
  2414 /**
       
  2415 	Method name is a bit dud in this state
       
  2416 	We notify the socket that it is Disconnected
       
  2417 	Provides better behaviour for the MSocketNotify - it doesn't end up
       
  2418 	with a Disconnect upcall whilst calling Read
       
  2419 **/
       
  2420 	{
       
  2421 	__ASSERT_DEBUG(aSAP.iNewDataToNotify == 0, PanicInState(ERfcommStateClosedWithData));
       
  2422 
       
  2423 	LOG(_L("SAP has no more data - socket now Disconnected"));
       
  2424 
       
  2425 	aSAP.iSocket->Disconnect();
       
  2426 	ChangeState(aSAP, CRfcommStateFactory::EClosed);
       
  2427 	}
       
  2428 
       
  2429 void TRfcommStateDisconnecting::Ioctl(CRfcommSAP& aSAP,TUint /*aLevel*/,TUint /*aName*/,TDes8* /*aOption*/)
       
  2430 	/**
       
  2431 	   An ioctl has been requested while we are in state disconnected.
       
  2432 
       
  2433 	   We fail all ioctls in this state.
       
  2434 	**/
       
  2435 	{
       
  2436 	__ASSERT_DEBUG(aSAP.iIoctlLevel == 0, PanicInState(ERfcommSAPTwoIoctls));
       
  2437 	__ASSERT_DEBUG(aSAP.iIoctlName == 0, PanicInState(ERfcommSAPTwoIoctls));
       
  2438 
       
  2439 	SignalError(aSAP, KErrDisconnected, MSocketNotify::EErrorIoctl);
       
  2440 	}
       
  2441 
       
  2442 void TRfcommStateDisconnecting::Shutdown(CRfcommSAP& aSAP)
       
  2443 	/**
       
  2444 	   We've been asked to close this side.
       
  2445 
       
  2446 	   Since the other end has already gone away, there's no need to
       
  2447 	   send anything, we can go straight to closed.
       
  2448 	**/
       
  2449 	{
       
  2450 	ChangeState(aSAP, CRfcommStateFactory::EClosed);	// Must enter before CanClose, since
       
  2451 														// this may delete us
       
  2452 	aSAP.iSocket->CanClose();
       
  2453 	}
       
  2454 
       
  2455 void TRfcommStateDisconnecting::FastShutdown(CRfcommSAP& aSAP)
       
  2456 	/**
       
  2457 	   We've been asked to close this side with extreme prejudice.
       
  2458 
       
  2459 	   Since the other end has already gone away, there's no need to
       
  2460 	   send anything, we can go straight to closed.  Note we will be
       
  2461 	   deleted when this returns.
       
  2462 	**/
       
  2463 	{
       
  2464 	ChangeState(aSAP, CRfcommStateFactory::EClosed);
       
  2465 	}