bluetooth/btstack/l2cap/l2capSAPSignalHandler.cpp
changeset 0 29b1cd4cb562
child 17 32ba20339036
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements the handling of l2cap signal packets (both inbound and outbound) from SAP interface
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <bt_sock.h>
       
    19 #include <bluetooth/logger.h>
       
    20 
       
    21 
       
    22 #include "l2capSAPSignalHandler.h"
       
    23 #include "l2capSigStates.h"
       
    24 #include "l2capSigPacketConnection.h"
       
    25 #include "l2capSigPacketConfigure.h"
       
    26 #include "l2capSigPacketDisconnection.h"
       
    27 #include "l2capSigPacketEcho.h"
       
    28 #include "l2capSigPacketCommandReject.h"
       
    29 #include "l2util.h"
       
    30 #include "l2sap.h"
       
    31 #include "l2cap.h"
       
    32 
       
    33 #include "l2capEntityConfig.h"
       
    34 #include "l2signalmgr.h"
       
    35 
       
    36 #ifdef __FLOG_ACTIVE
       
    37 _LIT8(KLogComponent, LOG_COMPONENT_L2CAP);
       
    38 #endif
       
    39 
       
    40 /*static*/ CL2CapSAPSignalHandler* CL2CapSAPSignalHandler::NewL(CL2CAPConnectionSAP& aSAP)
       
    41 	{
       
    42 	LOG_STATIC_FUNC
       
    43 	CL2CapSAPSignalHandler* self = new(ELeave) CL2CapSAPSignalHandler(aSAP);
       
    44 	CleanupStack::PushL(self);
       
    45 	self->ConstructL();
       
    46 	CleanupStack::Pop();
       
    47 	return self;
       
    48 	}
       
    49 
       
    50 // Disable warning WINS 4355: 'this' : used in base member initializer list
       
    51 // This will not cause any problems in this usage and is preferable to the use of a
       
    52 // non-owned pointer.
       
    53 #pragma warning (disable: 4355)
       
    54 CL2CapSAPSignalHandler::CL2CapSAPSignalHandler(CL2CAPConnectionSAP& aSAP)
       
    55  : CL2CapSignalHandler(),
       
    56    iSAP(&aSAP),
       
    57    iLocalBTAddress(TBTDevAddr(0)),
       
    58    iDefaultRTXTimerDuration(HL2CapCommand::KDefaultRTXTimerDuration),
       
    59    iERTXTimerDuration(HL2CapCommand::KDefaultERTXTimerDuration),
       
    60    iSigState(&aSAP.Protocol().SigStateFactory().GetState(CL2CAPSignalStateFactory::EClosed)),
       
    61    iSAPSignalHandlerTimerState(ETimerIdle)
       
    62 	{
       
    63 	LOG_FUNC
       
    64 	}
       
    65 #pragma warning (default: 4355)
       
    66 
       
    67 void CL2CapSAPSignalHandler::ConstructL()
       
    68 	{
       
    69 	LOG_FUNC
       
    70 	iChannelConfig = CL2CapChannelConfig::NewL(*this);
       
    71 	LOG2(_L("CL2CapSAPSignalHandler.iChannelConfig = %X.%X"), (TAny*)this, (TAny*)iChannelConfig)
       
    72 	}
       
    73 
       
    74 CL2CapSAPSignalHandler::~CL2CapSAPSignalHandler()
       
    75 	{
       
    76 	LOG_FUNC
       
    77 	DetachFromMux();
       
    78 	delete iChannelConfig;
       
    79 	
       
    80 	__ASSERT_DEBUG(iMuxer == NULL, Panic(EL2CAPSigHandlerDeletedWithResources));
       
    81 	// If our ConstructL leaves we will be deleted with iSAP non-NULL.  This is ok as
       
    82 	// the SAP will also be deleted as part of the cleanup process.  Because it's useful
       
    83 	// to keep this assert for the normal case we test iChannelConfig (which may never be
       
    84 	// NULL after ConstructL) to detect the case where ConstructL has left and iSAP may
       
    85 	// validly be non-NULL
       
    86 	__ASSERT_DEBUG((iSAP == NULL) || (iChannelConfig == NULL), Panic(EL2CAPSigHandlerDeletedWithResources));
       
    87 	}
       
    88 
       
    89 TInt CL2CapSAPSignalHandler::ConstructConnectionResponse(TUint8 aId, TConnectResponseResult aResult, TConnectResponseStatus aStatus/*= EConnectPendNoFurtherInfo*/)
       
    90 	{
       
    91 	LOG_FUNC
       
    92 	TInt rerr = KErrNone;
       
    93 	
       
    94 	HL2CapCommand* command = HConnectionResponse::New(aId, iLocalPort, iRemotePort, aResult, aStatus);
       
    95 	if(command)
       
    96 		{
       
    97 		AddToOutgoingQueue(command);
       
    98 		}
       
    99 	else
       
   100 		{
       
   101 		rerr = KErrNoMemory;
       
   102 		}
       
   103 	return rerr;
       
   104 	}
       
   105 
       
   106 TInt CL2CapSAPSignalHandler::ConstructConnectionRequest()
       
   107 	{
       
   108 	LOG_FUNC
       
   109 	TInt rerr = KErrNone;
       
   110 
       
   111 	HL2CapCommand* command = HConnectionRequest::New(iLocalPort, iRemotePort, CurrentRTXTimerDuration(iDefaultRTXTimerDuration), iERTXTimerDuration);
       
   112 	if(command)
       
   113 		{
       
   114 		AddToOutgoingQueue(command);
       
   115 		}
       
   116 	else
       
   117 		{
       
   118 		rerr = KErrNoMemory;
       
   119 		}
       
   120 	return rerr;
       
   121 	}
       
   122 
       
   123 
       
   124 TInt CL2CapSAPSignalHandler::ConstructConfigRequest()
       
   125 	{
       
   126 	LOG_FUNC
       
   127 	TInt rerr = KErrNone;
       
   128 
       
   129 	HL2CapCommand* command = HConfigureRequest::New(RemotePort(), *iChannelConfig, CurrentRTXTimerDuration(iDefaultRTXTimerDuration), iERTXTimerDuration);
       
   130 	if(command)
       
   131 		{
       
   132 		AddToOutgoingQueue(command);
       
   133 		}
       
   134 	else
       
   135 		{
       
   136 		rerr = KErrNoMemory;
       
   137 		}
       
   138 	return rerr;
       
   139 	}
       
   140 
       
   141 /**
       
   142 	Used for constructing a configuration response for unknown parameters
       
   143 	@internalComponent
       
   144 **/
       
   145 TInt CL2CapSAPSignalHandler::ConstructConfigResponse(TUint8 aId, TConfigFlags aFlags, TConfigResponseResult aResult, RMBufChain& aUnknownParameters)
       
   146 	{
       
   147 	LOG_FUNC
       
   148 	TInt rerr = KErrNone;
       
   149 
       
   150 	HConfigureResponse* command = HConfigureResponse::New(aId, RemotePort(), aFlags, aResult);
       
   151 	if(command)
       
   152 		{
       
   153 		command->AddUnknownOptionsToCommand(aUnknownParameters);
       
   154 		AddToOutgoingQueue(command);
       
   155 		}
       
   156 	else
       
   157 		{
       
   158 		rerr = KErrNoMemory;
       
   159 		}
       
   160 	return rerr;
       
   161 	}
       
   162 
       
   163 
       
   164 TInt CL2CapSAPSignalHandler::ConstructConfigResponse(TUint8 aId, TConfigFlags aFlags, TConfigResponseResult aResult)
       
   165 	{
       
   166 	LOG_FUNC
       
   167 	TInt rerr = KErrNone;
       
   168 
       
   169 	HConfigureResponse* command = HConfigureResponse::New(aId, RemotePort(), aFlags, aResult);
       
   170 	if(command)
       
   171 		{
       
   172 		// Only add options if this is not a response to a Config Request
       
   173 		// with the C-flag set.
       
   174 		if(aFlags & KConfigOptionContinuationMask)
       
   175 			{
       
   176 			command->WriteDataLength();
       
   177 			}
       
   178 		else if (aResult == EConfigSuccess || aResult == EConfigUnacceptableParams)
       
   179 			{
       
   180 			// Add the options
       
   181 			rerr = command->AddOptionsToCommand(*iChannelConfig, aResult);
       
   182 			if(rerr != KErrNone)
       
   183 				{
       
   184 				delete command;
       
   185 				command = NULL;
       
   186 				}
       
   187 			}
       
   188 		
       
   189 		if(command)
       
   190 			{
       
   191 			AddToOutgoingQueue(command);
       
   192 			}
       
   193 		}
       
   194 	else
       
   195 		{
       
   196 		rerr = KErrNoMemory;
       
   197 		}
       
   198 	return rerr;
       
   199 	}
       
   200 	
       
   201 TInt CL2CapSAPSignalHandler::ConstructDisconnectRequest()
       
   202 	{
       
   203 	LOG_FUNC
       
   204 	TInt rerr = KErrNone;
       
   205 	
       
   206 	HL2CapCommand* command = HDisconnectRequest::New(iLocalPort, iRemotePort, CurrentRTXTimerDuration(iDefaultRTXTimerDuration), iERTXTimerDuration);
       
   207 	if(command)
       
   208 		{
       
   209 		AddToOutgoingQueue(command);
       
   210 		}
       
   211 	else
       
   212 		{
       
   213 		rerr = KErrNoMemory;
       
   214 		}
       
   215 	return rerr;
       
   216 	}
       
   217 	
       
   218 TInt CL2CapSAPSignalHandler::ConstructDisconnectResponse(TUint8 aId)
       
   219 	{
       
   220 	LOG_FUNC
       
   221 	TInt rerr = KErrNone;
       
   222 
       
   223 	HL2CapCommand* command = HDisconnectResponse::New(aId, iLocalPort, iRemotePort);
       
   224 	if(command)
       
   225 		{
       
   226 		AddToOutgoingQueue(command);
       
   227 		}
       
   228 	else
       
   229 		{
       
   230 		rerr = KErrNoMemory;
       
   231 		}
       
   232 	return rerr;
       
   233 	}
       
   234 
       
   235 
       
   236 TBool CL2CapSAPSignalHandler::HandleConnectionResponse(HConnectionResponse* aConnectionResponse)
       
   237 	{
       
   238 	LOG_FUNC
       
   239 	TBool rcode = EFalse;
       
   240 	
       
   241 	// Check the response is for this CID.
       
   242 	if(aConnectionResponse->SourceCID() == iLocalPort)
       
   243 		{
       
   244 		// Check that the Connection Response has been requested.
       
   245 		HL2CapCommand* requestCommand = FindMatchingOutstandingRequest(EConnectionRequest, aConnectionResponse->ID());
       
   246 		if(requestCommand)
       
   247 			{
       
   248 			// If this has a pending result.  Re-start the the Extended RTX timer
       
   249 			// on the Request.
       
   250 			if(aConnectionResponse->Result() == EConnectPending)
       
   251 				{
       
   252 				requestCommand->StartRTXTimer(HL2CapCommand::EERTXTimer, *this);
       
   253 				}
       
   254 			else
       
   255 				{
       
   256 				// Delete the request.
       
   257 				delete requestCommand;
       
   258 				}
       
   259 
       
   260 			iSigState->ConnectResponse(*this, aConnectionResponse);		// the state m/c will update the Destination CID
       
   261 			}
       
   262 		else
       
   263 			{
       
   264 			LOG(_L("CL2CapSAPSignalHandler::HandleConnectionResponse, no matching req"));
       
   265 			}
       
   266 
       
   267 		// NOTE: If there was no Connection Request outstanding
       
   268 		// (i.e., requestCommand == NULL) but the command IS for this
       
   269 		// CID this could be a duplicate response, one that has arrived in
       
   270 		// the window between RTX expiry and retransmission, or just bogus.  
       
   271 		// Silently discard the packet.			
       
   272 		rcode = ETrue;
       
   273 		}
       
   274 
       
   275 	return rcode;
       
   276 	}
       
   277 
       
   278 
       
   279 TBool CL2CapSAPSignalHandler::HandleConfigureRequest(HConfigureRequest* aConfigRequest)
       
   280 	{
       
   281 	LOG_FUNC
       
   282 	TBool rcode = EFalse;
       
   283 	
       
   284 	// Check the response is for this CID.
       
   285 	if(aConfigRequest->DestinationCID() == iLocalPort)
       
   286 		{
       
   287 		iSigState->ConfigRequest(*this, aConfigRequest);
       
   288 		rcode = ETrue;
       
   289 		}
       
   290 
       
   291 	return rcode;
       
   292 	}	
       
   293 	
       
   294 
       
   295 TBool CL2CapSAPSignalHandler::HandleConfigureResponse(HConfigureResponse* aConfigResponse)	
       
   296 	{
       
   297 	LOG_FUNC
       
   298 	TBool rcode = EFalse;
       
   299 	
       
   300 	// Check the response is for this CID.
       
   301 	if(aConfigResponse->SourceCID() == iLocalPort)
       
   302 		{
       
   303 		// Check that the Config Response has been requested.
       
   304 		HL2CapCommand* requestCommand = FindMatchingOutstandingRequest(EConfigureRequest, aConfigResponse->ID());
       
   305 		if(requestCommand)
       
   306 			{
       
   307 			// Delete the corresponding request.
       
   308 			delete requestCommand;
       
   309 
       
   310 			iSigState->ConfigResponse(*this, aConfigResponse);
       
   311 			}
       
   312 		// NOTE: If there was no Configure Request outstanding
       
   313 		// (i.e., requestCommand == NULL) this could be a duplicate 
       
   314 		// response, or just bogus.  Silently discard the packet.			
       
   315 		rcode = ETrue;			
       
   316 		}
       
   317 		
       
   318 	return rcode;
       
   319 	}
       
   320 
       
   321 TBool CL2CapSAPSignalHandler::HandleDisconnectRequest(HDisconnectRequest* aDisconnectRequest)
       
   322 	{
       
   323 	LOG_FUNC
       
   324 	TBool rcode = EFalse;
       
   325 	
       
   326 	// Check the response is for this CID.
       
   327 	if(aDisconnectRequest->DestinationCID() == iLocalPort &&
       
   328 	   aDisconnectRequest->SourceCID() == iRemotePort)
       
   329 		{	
       
   330 		iSigState->DisconnectRequest(*this, aDisconnectRequest->ID());
       
   331 		rcode = ETrue;
       
   332 		}
       
   333 		
       
   334 	return rcode;
       
   335 	}
       
   336 	
       
   337 TBool CL2CapSAPSignalHandler::HandleDisconnectResponse(HDisconnectResponse* aDisconnectResponse)
       
   338 	{
       
   339 	LOG_FUNC
       
   340 	TBool rcode = EFalse;
       
   341 	
       
   342 	// Check the response is for this CID.
       
   343 	if(aDisconnectResponse->DestinationCID() == iRemotePort &&
       
   344 	   aDisconnectResponse->SourceCID() == iLocalPort)
       
   345 		{	
       
   346 		// Check that the Disconnect Response has been requested.
       
   347 		HL2CapCommand* requestCommand = FindMatchingOutstandingRequest(EDisconnectionRequest, aDisconnectResponse->ID());
       
   348 		if(requestCommand)
       
   349 			{
       
   350 			// Delete the corresponding request.
       
   351 			delete requestCommand;
       
   352 
       
   353 			iSigState->DisconnectResponse(*this);			
       
   354 			}
       
   355 		// NOTE: If there was no Disconnect Request outstanding
       
   356 		// (i.e., requestCommand == NULL) this could be a duplicate 
       
   357 		// response, or just bogus.  Silently discard the packet.			
       
   358 		rcode = ETrue;			
       
   359 		}
       
   360 		
       
   361 	return rcode;
       
   362 	}
       
   363 	
       
   364 
       
   365 TBool CL2CapSAPSignalHandler::HandleCommandReject(HCommandReject* aCommandReject)
       
   366 	{
       
   367 	LOG_FUNC
       
   368 	TBool rcode = EFalse;
       
   369 	
       
   370 	// Process the incoming command reject data
       
   371 	TL2CAPCommandRejectData rejectData;
       
   372 	
       
   373 	if (aCommandReject->RejectData(rejectData) != KErrNone) return rcode;
       
   374 
       
   375 	switch(rejectData.iReason)
       
   376 		{
       
   377 		case EInvalidCID:
       
   378 			{
       
   379 			TBool forThisChannel = EFalse;
       
   380 			
       
   381 			// To be considered as 'for this channel', either both pairs should match
       
   382 			// OR only one of the endpoints should be present and match.
       
   383 			if(rejectData.iLocalEndpoint != 0 &&
       
   384 			   rejectData.iLocalEndpoint == iRemotePort)
       
   385 				{
       
   386 				forThisChannel = ETrue;
       
   387 				}
       
   388 				
       
   389 			if(rejectData.iRemoteEndpoint != 0)
       
   390 				{
       
   391 				if(rejectData.iRemoteEndpoint == iLocalPort)
       
   392 			   		{
       
   393 			   		forThisChannel = ETrue;
       
   394 			   		}
       
   395 				else
       
   396 					{
       
   397 			   		forThisChannel = EFalse;
       
   398 			   		}
       
   399 				}
       
   400 
       
   401 			if(forThisChannel)
       
   402 				{
       
   403 				LOG1(_L("CL2CapSAPSignalHandler::HandleCommandReject(): forThisChannel = ETrue for commandID = 0x%04x"),aCommandReject->ID())
       
   404 				LOG2(_L("rejectData.iLocalEndpoint = 0x%04x, iRemotePort = 0x%04x"),rejectData.iLocalEndpoint,iRemotePort)
       
   405 				LOG2(_L("rejectData.iRemoteEndpoint = 0x%04x, iLocalPort = 0x%04x"),rejectData.iRemoteEndpoint,iLocalPort)
       
   406 				
       
   407 				// If there is no matching command then this rejection is not for this handler
       
   408 				if (FindMatchingOutstandingRequest(EMatchAnyL2CAPRequest,aCommandReject->ID()))
       
   409 					{
       
   410 					// The channel has been disconnected or is not
       
   411 					// recognised by the peer.  Error the channel.
       
   412 					iSigState->Error(*this, KErrL2PeerRejectedCommand, MSocketNotify::EErrorAllOperations);
       
   413 					rcode = ETrue;
       
   414 					}
       
   415 				else
       
   416 					{
       
   417 					LOG(_L("CL2CapSAPSignalHandler::HandleCommandReject(): No matching command is found, skipping it"))
       
   418 					}
       
   419 				}
       
   420 			break;
       
   421 			}
       
   422 		default:
       
   423 			break;
       
   424 		};
       
   425 					
       
   426 	return rcode;
       
   427 	}
       
   428 	
       
   429 void CL2CapSAPSignalHandler::CloneChannelConfig(CL2CapChannelConfig& aL2CAPChannelConfig)
       
   430 	{
       
   431 	LOG_FUNC
       
   432 	iChannelConfig->CloneChannelConfig(aL2CAPChannelConfig);
       
   433 	}
       
   434 
       
   435 
       
   436 TInt CL2CapSAPSignalHandler::UpdateChannelConfig(const TL2CapConfig& aAPIConfig)
       
   437 	{
       
   438 	LOG_FUNC
       
   439 	return iSigState->UpdateChannelConfig(*this, aAPIConfig);
       
   440 	}
       
   441 
       
   442 void CL2CapSAPSignalHandler::SetState(TL2CAPSigState& aState)
       
   443 	{
       
   444 	LOG_FUNC
       
   445 	LOG2(_L("CL2CapSAPSignalHandler::SetState 0x%08x -> 0x%.8x"), iSigState, &aState);
       
   446 	
       
   447 	iSigState->Exit(*this);
       
   448 	iSigState = &aState;
       
   449 	iSigState->Enter(*this);
       
   450 	}
       
   451 
       
   452 void CL2CapSAPSignalHandler::SetLocalPort(TL2CAPPort aPort)
       
   453 	{
       
   454 	LOG_FUNC
       
   455 	LOG1(_L("Setting local port to %d"), aPort);
       
   456 	iLocalPort = aPort;
       
   457 	}
       
   458 
       
   459 void CL2CapSAPSignalHandler::SetRemotePort(TL2CAPPort aPort)
       
   460 	{
       
   461 	LOG_FUNC
       
   462 	LOG1(_L("Setting remote port to %d"), aPort);
       
   463 	iRemotePort = aPort;
       
   464 	}
       
   465 
       
   466 void CL2CapSAPSignalHandler::SetRemName(TL2CAPSockAddr& aAddr)
       
   467 	{
       
   468 	LOG_FUNC
       
   469 	SetRemotePort(aAddr.Port());
       
   470 	}
       
   471 
       
   472 void CL2CapSAPSignalHandler::GetRemName(TL2CAPSockAddr& aAddr) const
       
   473 	{
       
   474 	LOG_FUNC
       
   475 	aAddr.SetBTAddr(RemoteBTAddress());
       
   476 	aAddr.SetPort(iRemotePort);
       
   477 	}
       
   478 
       
   479 void CL2CapSAPSignalHandler::SetLocalParameters(TL2CAPSockAddr& aAddr)
       
   480 	{
       
   481 	LOG_FUNC
       
   482 	iLocalBTAddress = aAddr.BTAddr();
       
   483 	LOGBTDEVADDR(iLocalBTAddress);	
       
   484 	SetLocalPort(aAddr.Port());
       
   485 	}
       
   486 
       
   487 void CL2CapSAPSignalHandler::GetLocalParameters(TL2CAPSockAddr& aAddr) const
       
   488 	{
       
   489 	LOG_FUNC
       
   490 	aAddr.SetBTAddr(iLocalBTAddress);
       
   491 	aAddr.SetPort(iLocalPort);
       
   492 	}
       
   493 	
       
   494 TInt CL2CapSAPSignalHandler::SetOption(TUint aLevel, TUint aName, const TDesC8& aOption)
       
   495 	{
       
   496 	LOG_FUNC
       
   497 	// iMuxer may be NULL
       
   498 	if (iMuxer != NULL)
       
   499 		{
       
   500 		return iMuxer->SetOption(aLevel, aName, aOption);
       
   501 		}
       
   502 	else
       
   503 		{
       
   504 		return KErrNotReady;
       
   505 		}
       
   506 	}
       
   507 	
       
   508 	
       
   509 TInt CL2CapSAPSignalHandler::GetOption(TUint aLevel, TUint aName, TDes8& aOption) const
       
   510 	{
       
   511 	LOG_FUNC
       
   512 	// iMuxer may be NULL
       
   513 	if (iMuxer != NULL)
       
   514 		{
       
   515 		return iMuxer->GetOption(aLevel, aName, aOption);
       
   516 		}
       
   517 	else
       
   518 		{
       
   519 		return KErrNotReady;
       
   520 		}
       
   521 	}
       
   522 
       
   523 void CL2CapSAPSignalHandler::SAPSignalHandlerRegistered(CL2CAPMux& aMuxer, TL2CAPEntityConfig& aEntityConfig)
       
   524 	{
       
   525 	LOG_FUNC
       
   526 	__ASSERT_DEBUG(iMuxer == NULL, Panic(EL2CAPSAPSignalHandlerRegisteredTwice));
       
   527 	iMuxer = &aMuxer;
       
   528 	iSAP->SetRemoteDev(iMuxer->RemoteBTAddr());
       
   529 	iChannelConfig->RegisterL2CapEntityConfig(aEntityConfig);
       
   530 	}
       
   531 
       
   532 
       
   533 // Indicates that the baseband is up and going and that all the objects are tied together ok.
       
   534 void CL2CapSAPSignalHandler::LinkUp()
       
   535 	{
       
   536 	LOG_FUNC
       
   537 	iSAP->LinkUp();
       
   538 	}
       
   539 
       
   540 void CL2CapSAPSignalHandler::Error(TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction)
       
   541 	{
       
   542 	LOG_FUNC
       
   543 	iSigState->Error(*this, aErrorCode, aErrorAction);
       
   544 	}
       
   545 	
       
   546 //Called by the state machine when we go into channel reconfiguration
       
   547 void CL2CapSAPSignalHandler::ReconfiguringChannel()
       
   548 	{
       
   549 	LOG_FUNC
       
   550 	iSAP->ReconfiguringChannel();
       
   551 	}
       
   552 
       
   553 void CL2CapSAPSignalHandler::SignalHandlerDisconnectedCanClose()
       
   554 	{
       
   555 	LOG_FUNC
       
   556 	// If the SAP exists signal the disconnect.  Otherwise delete this
       
   557 	// signal handler.
       
   558 	if(iSAP)
       
   559 		{
       
   560 		iSAP->ChannelClosed();
       
   561 		}
       
   562 	else
       
   563 		{
       
   564 		delete this;
       
   565 		}
       
   566 	}
       
   567 
       
   568 void CL2CapSAPSignalHandler::SignalHandlerErrorD(TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction)
       
   569 	{
       
   570 	LOG_FUNC
       
   571 	// If the SAP exists signal the error.  Otherwise delete this
       
   572 	// signal handler.
       
   573 	if(iSAP)
       
   574 		{
       
   575 		iSAP->SignalHandlerError(aErrorCode, aErrorAction);
       
   576 		}
       
   577 	else
       
   578 		{
       
   579 		delete this;
       
   580 		}
       
   581 	}
       
   582 
       
   583 //Called by the link signal handler 	
       
   584 TInt CL2CapSAPSignalHandler::PassiveConnectionRequest(const TBTDevAddr& aAddr,HConnectionRequest* aConnectionRequest)
       
   585 	{
       
   586 	LOG_FUNC
       
   587 	TInt rerr = KErrNone;
       
   588 	CL2CAPConnectionSAP *clonedSAP = NULL;
       
   589 
       
   590 	TUint8 id = aConnectionRequest->ID();
       
   591 	TL2CAPPort scid = aConnectionRequest->SourceCID(); 
       
   592 
       
   593 	// Check if the SAP is ready to accept a connection.
       
   594 	// Note.  If the SAP is not in the listening state this
       
   595 	// will return with the not ready error code.
       
   596 	if(!iSAP->CanAcceptConnection())
       
   597 		{
       
   598 		rerr = KErrNotReady;
       
   599 		}
       
   600 	else
       
   601 		{
       
   602 		if((clonedSAP = iSAP->CloneListeningSAP(aAddr)) == NULL)
       
   603 			{
       
   604 			rerr = KErrNoMemory;
       
   605 			}
       
   606 		else
       
   607 			{
       
   608 			CL2CapSAPSignalHandler& clonedSH = clonedSAP->SignalHandler();
       
   609 
       
   610 			clonedSH.iRemotePort = scid;
       
   611 			clonedSH.iOutstandingRequestID = id;
       
   612 
       
   613 			clonedSH.CloneChannelConfig(*iChannelConfig);
       
   614 			rerr = iSAP->Protocol().MuxController().AttachPassiveSignalHandler(clonedSH, aAddr);
       
   615 			}
       
   616 		}
       
   617 	return rerr;
       
   618 	}
       
   619 
       
   620 void CL2CapSAPSignalHandler::ActiveConnectionRequest()
       
   621 	{
       
   622 	LOG_FUNC
       
   623 	iMuxer->CompleteACLConnect(NULL);
       
   624 	}
       
   625 
       
   626 void CL2CapSAPSignalHandler::L2CapEntityConfigUpdated()
       
   627  	{
       
   628  	LOG_FUNC
       
   629  	if (iOpenChannelRequestAwaitingPeerEntityConfig)
       
   630  		{
       
   631  		// SAP state machine requested that we open the channel before we could do it.
       
   632  		// We can do it now.
       
   633  		iOpenChannelRequestAwaitingPeerEntityConfig = EFalse;
       
   634  		iSigState->OpenChannelRequest(*this);
       
   635  		}
       
   636  	}
       
   637 
       
   638 TBool CL2CapSAPSignalHandler::DelayConfigRequest()
       
   639 	{
       
   640 	LOG_FUNC
       
   641 	iAwaitingConfigRequestDelayTimer = iSAPSignalHandlerTimerState==EConfigRequestDelayTimer;
       
   642 
       
   643 	return iAwaitingConfigRequestDelayTimer; //true if we are delaying
       
   644 	}
       
   645 				
       
   646 void CL2CapSAPSignalHandler::ConfigRequestDelayTimerExpiry()	
       
   647  	{
       
   648  	LOG_FUNC
       
   649  	if(iAwaitingConfigRequestDelayTimer)
       
   650  		{
       
   651  		iAwaitingConfigRequestDelayTimer = EFalse;
       
   652 		ConfigureChannelRequest();
       
   653  		}
       
   654  	}
       
   655 
       
   656 void CL2CapSAPSignalHandler::CloseChannelRequest()
       
   657 	{
       
   658 	LOG_FUNC
       
   659 	iSigState->CloseChannelRequest(*this);
       
   660 	}
       
   661 
       
   662 void CL2CapSAPSignalHandler::OpenChannelRequest()
       
   663 	{
       
   664 	LOG_FUNC
       
   665 	__ASSERT_DEBUG(!iOpenChannelRequestAwaitingPeerEntityConfig,
       
   666 				   Panic(EL2CAPOpenChannelRequestCalledTwice));
       
   667 
       
   668 	if (IsPeerInfoDefined())
       
   669 		{
       
   670 		iSigState->OpenChannelRequest(*this);
       
   671 		}
       
   672 	else
       
   673 		{
       
   674 		iOpenChannelRequestAwaitingPeerEntityConfig = ETrue;
       
   675 		// We'll realize the OpenChannelRequest as soon as we receive
       
   676 		// the Information Response.
       
   677 		}
       
   678 	}
       
   679 
       
   680 void CL2CapSAPSignalHandler::ConnectRequestReceived()
       
   681 	{
       
   682 	LOG_FUNC
       
   683 	iSigState->ConnectRequestReceived(*this);
       
   684 	}
       
   685 
       
   686 void CL2CapSAPSignalHandler::ConfigureChannelRequest()
       
   687 	{
       
   688 	LOG_FUNC
       
   689 	iSigState->ConfigureChannelRequest(*this);
       
   690 	}
       
   691 
       
   692 void CL2CapSAPSignalHandler::PendingCommandsDrained()
       
   693 	{
       
   694 	LOG_FUNC
       
   695 	iSigState->PendingCommandsDrained(*this);
       
   696 	}
       
   697 
       
   698 // SAP signal handler timer methods.	
       
   699 /*static*/ TInt CL2CapSAPSignalHandler::TimerExpired(TAny* aSAPSignalHandler)
       
   700 	{
       
   701 	LOG_STATIC_FUNC
       
   702 	CL2CapSAPSignalHandler* sh = reinterpret_cast<CL2CapSAPSignalHandler*>(aSAPSignalHandler);
       
   703 	sh->HandleTimerExpired();
       
   704 	return EFalse;
       
   705 	}
       
   706 
       
   707 void CL2CapSAPSignalHandler::StartConfigurationTimer()
       
   708 	{
       
   709 	LOG_FUNC
       
   710 	switch(iSAPSignalHandlerTimerState)
       
   711 		{
       
   712 		case EConfigurationTimer:
       
   713 		case EConfigRequestDelayTimer:
       
   714 			// The timer is already running. Cancel it and start it again.
       
   715 			BTSocketTimer::Remove(iSAPSignalHandlerTimerEntry);
       
   716 			iSAPSignalHandlerTimerState = ETimerIdle;
       
   717 			break;
       
   718 					
       
   719 		case ETimerIdle:
       
   720 		default:
       
   721 			// No timer running, nothing needs to be done.
       
   722 			break;
       
   723 		};
       
   724 
       
   725 	if(iSAPSignalHandlerTimerState == ETimerIdle)
       
   726 		{
       
   727 		TCallBack cb(TimerExpired, this);
       
   728 		iSAPSignalHandlerTimerEntry.Set(cb);
       
   729 		BTSocketTimer::Queue(KL2ConfigRequestDelayTimout, 
       
   730 		                     iSAPSignalHandlerTimerEntry);
       
   731 		iSAPSignalHandlerTimerState = EConfigRequestDelayTimer;
       
   732 		}
       
   733 	}
       
   734 	
       
   735 void CL2CapSAPSignalHandler::CancelTimer()
       
   736 	{
       
   737 
       
   738 	LOG_FUNC
       
   739 	if(iSAPSignalHandlerTimerState != ETimerIdle)
       
   740 		{
       
   741 		BTSocketTimer::Remove(iSAPSignalHandlerTimerEntry);
       
   742 		iSAPSignalHandlerTimerState = ETimerIdle;
       
   743 		}
       
   744 	}
       
   745 
       
   746 void CL2CapSAPSignalHandler::HandleTimerExpired()
       
   747 	{
       
   748 	LOG_FUNC
       
   749 	switch(iSAPSignalHandlerTimerState)
       
   750 		{
       
   751 		case ETimerIdle:
       
   752 			Panic(EL2CAPSSHTimerExpiredWhileInIdleState);
       
   753 			break;
       
   754 			
       
   755 		case EConfigRequestDelayTimer:
       
   756 			{
       
   757 			TCallBack cb(TimerExpired, this);
       
   758 			iSAPSignalHandlerTimerEntry.Set(cb);
       
   759 			BTSocketTimer::Queue(KL2ConfigWatchdogTimeout * KL2ProtocolSecondTimerMultiplier, 
       
   760 			                     iSAPSignalHandlerTimerEntry);
       
   761 			iSAPSignalHandlerTimerState = EConfigurationTimer;
       
   762 			ConfigRequestDelayTimerExpiry();
       
   763 			}
       
   764 			break;
       
   765 			
       
   766 		case EConfigurationTimer:
       
   767 			iSAPSignalHandlerTimerState = ETimerIdle;
       
   768 			iSigState->ConfigurationTimerExpiry(*this);
       
   769 			break;
       
   770 
       
   771 		default:
       
   772 			Panic(EL2CAPInvalidSAPSHTimerState);
       
   773 			break;
       
   774 		};		
       
   775 	}
       
   776 
       
   777 void CL2CapSAPSignalHandler::DetachFromMux()
       
   778 	{
       
   779 	LOG_FUNC
       
   780 	__ASSERT_DEBUG(iPendingCommands.IsEmpty(), Panic(EL2CAPSigHandlerDeletedWithResources));
       
   781 	__ASSERT_DEBUG(iCommandsAwaitingResponse.IsEmpty(), Panic(EL2CAPSigHandlerDeletedWithResources));
       
   782 
       
   783 	// If this is a listening Socket then it will not have
       
   784 	// an associated muxer to detach.
       
   785 	if(iMuxer)
       
   786 		{
       
   787 		iLink.Deque();
       
   788 		
       
   789 		iMuxer->DetachFromMux(*this);
       
   790 
       
   791 		// Check to see if the stack needs to be brought down
       
   792 		iMuxer->MuxController().Protocol().TryToClose();
       
   793 		
       
   794 		iMuxer = NULL;
       
   795 
       
   796 		// If the SAP's Config object has registered with the Entity
       
   797 		// Config object then remove this association.
       
   798 		iChannelConfig->DetachChannelConfig();
       
   799 		}
       
   800 	}
       
   801 	
       
   802 void CL2CapSAPSignalHandler::SAPClosed()
       
   803 	{
       
   804 	LOG_FUNC
       
   805 	// The SAP is about to be detached from this signal handler.
       
   806 	// Ensure no park overrides are active.
       
   807 	UndoOverrideParkMode();
       
   808 	
       
   809 	// Check if this SH has any unsent commands
       
   810 	// outstanding.
       
   811 	iSAP = NULL;
       
   812 	if(iMuxer == NULL)	
       
   813 		{
       
   814 		delete this;
       
   815 		}
       
   816 	}
       
   817 	
       
   818 void CL2CapSAPSignalHandler::CommandResponseFailure(HL2CapCommand* aCommand)
       
   819 	{
       
   820 	LOG_FUNC
       
   821 	// Pass on this error to the state and delete the command.
       
   822 	iSigState->Error(*this, KErrL2CAPRequestTimeout, MSocketNotify::EErrorAllOperations);
       
   823 	delete aCommand;
       
   824 	}
       
   825 	
       
   826 TInt CL2CapSAPSignalHandler::SendEchoRequest(const TDes8* aData)
       
   827 	{
       
   828 	LOG_FUNC
       
   829 	TInt rerr = KErrNone;
       
   830 	if(iMuxer)
       
   831 		{
       
   832 		// Check to ensure that the echo payload isn't too big to send
       
   833 		if ((!aData) || (aData->Size() <= iMuxer->SigMTU() - HEchoRequest::KEchoRequestEmptyLength))
       
   834 			{
       
   835 			rerr = iMuxer->SendEchoRequest(aData, *this);
       
   836 			}
       
   837 		else
       
   838 			{
       
   839 		    rerr = KErrTooBig;
       
   840 			}
       
   841 		}
       
   842 	else
       
   843 		{
       
   844 		rerr = KErrDisconnected;
       
   845 		}
       
   846 	return rerr;
       
   847 	}
       
   848 
       
   849 void CL2CapSAPSignalHandler::EchoResponseReceived(const TDesC8* aData)
       
   850 	{
       
   851 	LOG_FUNC
       
   852 	if(iSAP)
       
   853 		{
       
   854 		iSAP->EchoResponseReceived(aData);
       
   855 		}
       
   856 	}
       
   857 
       
   858 TInt CL2CapSAPSignalHandler::SetRTXTimerDuration(TUint8 aDuration)
       
   859 	{
       
   860 	LOG_FUNC
       
   861 	TInt rerr = KErrNone;
       
   862 	if(aDuration > 0 && aDuration < HL2CapCommand::KMaxRTXTimerDuration)
       
   863 		{
       
   864 		iDefaultRTXTimerDuration = aDuration;
       
   865 		}
       
   866 	else
       
   867 		{
       
   868 		rerr = KErrArgument;	
       
   869 		}
       
   870 	return rerr;
       
   871 	}
       
   872 	
       
   873 TInt CL2CapSAPSignalHandler::SetERTXTimerDuration(TUint16 aDuration)
       
   874 	{
       
   875 	LOG_FUNC
       
   876 	TInt rerr = KErrNone;
       
   877 	if(aDuration > 0 && aDuration < HL2CapCommand::KMaxERTXTimerDuration)
       
   878 		{
       
   879 		iERTXTimerDuration = aDuration;
       
   880 		}
       
   881 	else
       
   882 		{
       
   883 		rerr = KErrArgument;	
       
   884 		}
       
   885 	return rerr;	
       
   886 	}
       
   887 	
       
   888 void CL2CapSAPSignalHandler::OverrideParkMode()
       
   889 	{
       
   890 	LOG_FUNC
       
   891 	// Override Park mode.  A reference to the SAP is required
       
   892 	// to get the remote device address.
       
   893 	if(iSAP)
       
   894 		{
       
   895 		iSAP->Protocol().ControlPlane().ModifyPhysicalLink(EOverridePark, iSAP->RemoteDev());
       
   896 		}
       
   897 	}
       
   898 	
       
   899 void CL2CapSAPSignalHandler::UndoOverrideParkMode()
       
   900 	{
       
   901 	LOG_FUNC
       
   902 	// Remove Park mode override.  A reference to the SAP is required
       
   903 	// to get the remote device address.
       
   904 	if(iSAP)
       
   905 		{
       
   906 		iSAP->Protocol().ControlPlane().ModifyPhysicalLink(EUndoOverridePark, iSAP->RemoteDev());
       
   907 		}
       
   908 	}
       
   909 	
       
   910 void CL2CapSAPSignalHandler::OverrideLPMWithTimeout()
       
   911 	{
       
   912 	LOG_FUNC
       
   913 	// Temporarily override all low power modes.  A reference to the SAP is required
       
   914 	// to get the remote device address.
       
   915 	if(iSAP)
       
   916 		{
       
   917 		iSAP->Protocol().ControlPlane().ModifyPhysicalLink(EOverrideLPMWithTimeout, iSAP->RemoteDev());
       
   918 		}
       
   919 	}
       
   920