bluetooth/btstack/l2cap/l2sap.cpp
changeset 0 29b1cd4cb562
child 8 2b6718f05bdb
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements the code for the connected and group L2CAP saps
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <bluetooth/logger.h>
       
    19 
       
    20 #include "l2sap.h"
       
    21 
       
    22 #include "l2sapstates.h"
       
    23 #include "l2cap.h"
       
    24 
       
    25 #include "l2util.h"
       
    26 
       
    27 #include "L2CapSDUQueue.h"
       
    28 #include "L2CapDataController.h"
       
    29 #include "l2capSAPSignalHandler.h"
       
    30 #include "L2types.h"
       
    31 
       
    32 #include "L2CapDebugControlInterface.h"
       
    33 #include "l2capCommand.h"
       
    34 
       
    35 #ifdef __FLOG_ACTIVE
       
    36 _LIT8(KLogComponent, LOG_COMPONENT_L2CAP);
       
    37 #endif
       
    38 
       
    39 CL2CAPConnectionSAP* CL2CAPConnectionSAP::NewL(CL2CAPProtocol& aProt)
       
    40 	{
       
    41 	LOG_STATIC_FUNC
       
    42 	// Create and return a new SAP
       
    43 	CL2CAPConnectionSAP* sap= new (ELeave) CL2CAPConnectionSAP(aProt);
       
    44 	CleanupStack::PushL(sap);
       
    45 	sap->ConstructL();
       
    46 	CleanupStack::Pop();
       
    47 	return sap;
       
    48 	}
       
    49 
       
    50 void CL2CAPConnectionSAP::ConstructL()
       
    51 	{
       
    52 	LOG_FUNC
       
    53 	CBluetoothSAP::ConstructL();
       
    54 	TCallBack cb(NewDataAsyncCallBack, this);
       
    55 	iNewDataAsyncCallBack = new (ELeave)CAsyncCallBack(cb, EActiveHighPriority);
       
    56 	iL2CapSAPSignalHandler = CL2CapSAPSignalHandler::NewL(*this);
       
    57 	LOG2(_L("CL2CAPConnectionSAP.iL2CapSAPSignalHandler = %X.%X"), (TAny*)this, (TAny*)iL2CapSAPSignalHandler)
       
    58 	}
       
    59 
       
    60 CL2CAPConnectionSAP::CL2CAPConnectionSAP(CL2CAPProtocol& aProt)
       
    61  : CBluetoothSAP(aProt.SecMan(), aProt.CodMan()),
       
    62    iProtocol(aProt),
       
    63    iShutdownReceived(ESAPShutdownNone),
       
    64    iSocketErrorCode(KErrNone),
       
    65    iSocketErrorAction(MSocketNotify::TOperationBitmasks(0))
       
    66 	{
       
    67 	LOG_FUNC
       
    68 	iState=&aProt.StateFactory().GetState(CL2CAPSAPStateFactory::EClosed);
       
    69 
       
    70 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::ESAP,
       
    71 	                             L2capDebugInfo::EAllocated));
       
    72 	}
       
    73 
       
    74 
       
    75 
       
    76 CL2CAPConnectionSAP::~CL2CAPConnectionSAP()
       
    77 /**
       
    78    SAP destructor.
       
    79    Called when the socket deletes the SAP.
       
    80 */
       
    81 	{
       
    82 	LOG_FUNC
       
    83 
       
    84 	__ASSERT_DEBUG(iClones.Count() == 0, Panic(EL2CAPClonesExistDuringSAPDestructor));
       
    85 
       
    86 	// Ensure that everything is completely shutdown.
       
    87 	iState->FastShutdown(*this);
       
    88 
       
    89 	// Inform the signal handler that the SAP is being destructed.
       
    90 	// The SH will normally destroy itself unless it has a message
       
    91 	// that still needs to be sent.
       
    92 	if(iL2CapSAPSignalHandler)
       
    93 		{
       
    94 		iL2CapSAPSignalHandler->SAPClosed();
       
    95 		}
       
    96 
       
    97 	__ASSERT_DEBUG(iL2CapDataQueue == NULL, Panic(EL2CAPSDUQueueStillExistsDuringSAPDestructor));
       
    98 		
       
    99 	delete iNewDataAsyncCallBack;
       
   100 	iClones.Close();
       
   101 
       
   102 	//We may be still attached to the listening SAP if the connection was not fully completed before shutdown
       
   103 	//No checking needed because iListeningSAP will be NULL if this is the listening SAP or we are already 
       
   104 	//detached from the listeningSAP 
       
   105 	DetachFromListeningSAP();
       
   106 
       
   107 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::ESAP,
       
   108 	                             L2capDebugInfo::EDeleted));
       
   109 	}
       
   110 
       
   111 
       
   112 TBool CL2CAPConnectionSAP::CanAcceptConnection() const
       
   113 	{
       
   114 	LOG_FUNC
       
   115 	return (TotalOutstandingCloneCount() < iMaxAcceptingQCount);
       
   116 	}
       
   117 
       
   118 TUint8 CL2CAPConnectionSAP::TotalOutstandingCloneCount() const
       
   119    	{
       
   120 	LOG_FUNC
       
   121    	return static_cast<TUint8>(iClones.Count());
       
   122    	}
       
   123 
       
   124 CL2CAPConnectionSAP* CL2CAPConnectionSAP::CloneListeningSAP(const TBTDevAddr& aAddr)
       
   125 	{
       
   126 	LOG_FUNC
       
   127 	
       
   128 	TInt rerr = KErrNone;
       
   129 	CL2CAPConnectionSAP* clone = NULL;
       
   130 
       
   131 	TRAP(rerr, clone = NewL(iProtocol));
       
   132 	if(rerr == KErrNone)
       
   133 		{
       
   134 		if(!EnqueClone(clone))
       
   135 			{
       
   136 			delete clone;
       
   137 			clone = NULL;
       
   138 			}
       
   139 		else
       
   140 			{
       
   141 			clone->SetState(iState->iFactory.GetState(CL2CAPSAPStateFactory::EPassiveLinkPending));
       
   142 			clone->SetListeningSAP(*this);
       
   143 			
       
   144 			// Copy the details required for security.
       
   145 			clone->iSecurity = iSecurity;
       
   146 			clone->iRemoteDev = aAddr; 
       
   147 			}
       
   148 		}
       
   149 	return clone;
       
   150 	}
       
   151 
       
   152 
       
   153 TBool CL2CAPConnectionSAP::EnqueClone(CL2CAPConnectionSAP* aSAP)
       
   154 	{
       
   155 	LOG_FUNC
       
   156 	TInt rerr = iClones.Append(aSAP);
       
   157 	return (rerr == KErrNone);
       
   158 	}
       
   159 
       
   160 TBool CL2CAPConnectionSAP::DequeClone(CL2CAPConnectionSAP* aSAP)
       
   161 	{
       
   162 	LOG_FUNC
       
   163 	TBool rcode = EFalse;
       
   164 	TInt ix = iClones.Find(aSAP);
       
   165 
       
   166 	if(ix != KErrNotFound)
       
   167 		{
       
   168 		iClones.Remove(ix);
       
   169 		rcode = ETrue;
       
   170 		}
       
   171 	return rcode;
       
   172 	}
       
   173 
       
   174 void CL2CAPConnectionSAP::DeleteAllClones()
       
   175 /**
       
   176    This function is called by TL2CAPSAPStateListening::Exit() to clear
       
   177    the iClones queue and delete all the clones. However, any clones
       
   178    with their iAcceptingPending flag raised are owned by a socket,
       
   179    so they shouldn't be deleted. Instead their pointer to this SAP
       
   180    should be nulled, then they should be removed from the queue.
       
   181 **/
       
   182 	{
       
   183 	LOG_FUNC
       
   184 	
       
   185 	for(TInt i=iClones.Count()-1;i>=0;i--)
       
   186 		{
       
   187 		if(iClones[i]->IsAcceptPending())
       
   188 			{
       
   189 			iClones[i]->DetachFromListeningSAP();
       
   190 			}
       
   191 		}
       
   192 	iClones.ResetAndDestroy();
       
   193 	}
       
   194 
       
   195 void CL2CAPConnectionSAP::DeleteSAP()
       
   196 	{
       
   197 	LOG_FUNC
       
   198 	delete this;
       
   199 	}
       
   200 	
       
   201 void CL2CAPConnectionSAP::SocketConnectComplete()
       
   202 /**
       
   203    A Clone has completed a connection, so we tell our socket.
       
   204    
       
   205    Send the socket a ConnectComplete, the clone remains in the listening SAPs clone 
       
   206    queue, but its iAcceptPending flag is raised. Logically ownership of the clone has
       
   207    been transferred from the listening SAP to the socket, however the listening SAP 
       
   208    keeps a pointer until the socket calls Start(). 
       
   209 **/
       
   210 	{
       
   211 	LOG_FUNC
       
   212 
       
   213 	// There was a mysterious problem with AVDTP signalling channel connections
       
   214 	// which suggested that iL2CapDataQueue was 0 when BearerConnectionComplete was
       
   215 	// being called. The problem has disappeared but added this just in case it comes
       
   216 	// back again.
       
   217 	__ASSERT_DEBUG(iL2CapDataQueue != NULL, Panic(EL2CAPSduQNotExisitantInConnectComplete));
       
   218 
       
   219 	if(iListeningSAP)
       
   220 		{
       
   221 		SetState(iState->iFactory.GetState(CL2CAPSAPStateFactory::EAccepting));
       
   222 		iAcceptPending = ETrue;
       
   223 		iListeningSAP->Socket()->ConnectComplete(*this);
       
   224 		}
       
   225 	else
       
   226 		{
       
   227 		SetState(iState->iFactory.GetState(CL2CAPSAPStateFactory::EAwaitingInitialData));
       
   228 		Socket()->ConnectComplete();
       
   229 		}
       
   230 	}
       
   231 
       
   232 /*static*/ TInt CL2CAPConnectionSAP::NewDataAsyncCallBack(TAny* aSAP)
       
   233 	{
       
   234 	LOG_STATIC_FUNC
       
   235 	CL2CAPConnectionSAP* sap = static_cast<CL2CAPConnectionSAP*>(aSAP);
       
   236 	sap->iState->NewDataAsyncCallBack(*sap);
       
   237 	return EFalse;
       
   238 	}
       
   239 
       
   240 void CL2CAPConnectionSAP::LocalName(TSockAddr& anAddr) const
       
   241 /**
       
   242 	Read the Local Name into aAddr.
       
   243 	Note: On protocol start-up, the protocol might not have received the
       
   244 	BTAddr back from the HW when this is called... :-(
       
   245 	So the user should use the read local address ioctl to be sure of 
       
   246 	getting the right result.
       
   247 
       
   248 **/
       
   249 	{
       
   250 	LOG_FUNC
       
   251 
       
   252 	// Copy iLocalPort into TSockAddr and return
       
   253 	TL2CAPSockAddr& addr = TL2CAPSockAddr::Cast(anAddr);
       
   254 	iL2CapSAPSignalHandler->GetLocalParameters(addr);
       
   255 	}
       
   256 
       
   257 
       
   258 TInt CL2CAPConnectionSAP::SetLocalName(TSockAddr& anAddr)
       
   259 	{
       
   260 	LOG_FUNC
       
   261 
       
   262 	TL2CAPSockAddr l2capAddr = TL2CAPSockAddr::Cast(anAddr);
       
   263 	TL2CAPPort psm = l2capAddr.Port();
       
   264 	TInt err = KErrNone;
       
   265 
       
   266 	if(psm == KL2CAPPassiveAutoBind)
       
   267 		{
       
   268 		// User wishes for us to choose free ServerChannel
       
   269 		err = Protocol().MuxController().FindFreeUserPSM(psm);
       
   270 		if(err == KErrNone)
       
   271 			{
       
   272 			l2capAddr.SetPort(psm);
       
   273 			}
       
   274 		}
       
   275 	else
       
   276 		{
       
   277 		// User supplied explicit PSM.  Check that the value is odd.
       
   278 		if(psm & 0x0001)
       
   279 			{
       
   280 			// Valid, so see if available
       
   281 			if(Protocol().MuxController().FindIdleSignalHandler(psm))
       
   282 				{//psm in use already
       
   283 				err = KErrInUse;
       
   284 				}
       
   285 			}
       
   286 		else
       
   287 			{
       
   288 			// PSM not valid (as per 1.0B spec)
       
   289 			err = KErrArgument;
       
   290 			}
       
   291 		}
       
   292 
       
   293 
       
   294 	if (err == KErrNone)
       
   295 		{
       
   296 		iL2CapSAPSignalHandler->SetLocalParameters(l2capAddr);	
       
   297 		iState->Bound(*this);
       
   298 		iSecurity = l2capAddr.BTSecurity();
       
   299 		}
       
   300 
       
   301 	return err;
       
   302 	}
       
   303 
       
   304 void CL2CAPConnectionSAP::RemName(TSockAddr& anAddr) const
       
   305 	{
       
   306 	LOG_FUNC
       
   307 	//Return the remote name
       
   308 
       
   309 	// Copy iRemoteDev and iRemotePort into TSockAddr and return
       
   310 	TL2CAPSockAddr& addr = TL2CAPSockAddr::Cast(anAddr);
       
   311 	iL2CapSAPSignalHandler->GetRemName(addr);
       
   312 	}
       
   313 
       
   314 TInt CL2CAPConnectionSAP::SetRemName(TSockAddr& anAddr)
       
   315 	{
       
   316 	LOG_FUNC
       
   317 	
       
   318 	// Copy this over
       
   319 	TL2CAPSockAddr& addr = TL2CAPSockAddr::Cast(anAddr);
       
   320 	iL2CapSAPSignalHandler->SetRemName(addr);
       
   321 	
       
   322 	// Set the security and remote address values in the base class.
       
   323 	// This is required for security handling.
       
   324 	iSecurity = addr.BTSecurity();	//outgoing security
       
   325 	iRemoteDev = addr.BTAddr();
       
   326 	
       
   327 	LOG1(_L("L2CAP [l2sap.cpp]: Set remname to port %d, Device...."), addr.Port());
       
   328 	LOGHEXDESC(addr.BTAddr().Des());
       
   329 	return KErrNone;
       
   330 	}
       
   331 
       
   332 const TBTDevAddr& CL2CAPConnectionSAP::RemoteDev() const
       
   333 	{
       
   334 	LOG_FUNC
       
   335 	return iRemoteDev;
       
   336 	}
       
   337 
       
   338 void CL2CAPConnectionSAP::SetRemoteDev(const TBTDevAddr& aAddr)
       
   339 	{
       
   340 	LOG_FUNC
       
   341 	iRemoteDev = aAddr;
       
   342 	LOGBTDEVADDR(iRemoteDev);
       
   343 	}
       
   344 
       
   345 TUint CL2CAPConnectionSAP::GetOptimalMTUSize(TUint aMTU, TUint aPduSize, TBool aBasicMode) const
       
   346 	{
       
   347 	LOG_FUNC
       
   348 
       
   349 	// If the negotiated MTU minus any overhead will fit into the optimal PDU then that
       
   350 	// is the optimal MTU. The overhead will differ for basic and non-basic mode, for basic mode
       
   351 	// we have to consider the SDU overhead as there is no fragment overhead and for non-basic we 
       
   352 	// consider the PDU overhead only (the additional SDU overhead is taken account of later if 
       
   353 	// more than one PDU is required for the optimal MTU).
       
   354 	TUint optimalMTU = aMTU;
       
   355 
       
   356 	// Calculate the size of the MTU + any overhead assuming that the MTU is not segmented
       
   357 	TUint singlePduSize = aBasicMode ? (aMTU + CL2CapSDU::GetSDUOverhead(aBasicMode)) : aMTU;
       
   358 
       
   359 	// If the unsegmented MTU + overhead can fit into the optimal PDU size then no 
       
   360 	// further calculation is required
       
   361 	if(singlePduSize > aPduSize)
       
   362 		{
       
   363 		// The MTU will need to be segmented / fragmented (depending on L2CAP mode).
       
   364 		// Calculate an MTU size that will be a factor of the PDU size.
       
   365 		optimalMTU = aMTU - ((aMTU + CL2CapSDU::GetSDUOverhead(aBasicMode)) % aPduSize); 
       
   366 		}
       
   367 
       
   368 	return optimalMTU;
       
   369 	}
       
   370 
       
   371 TInt CL2CAPConnectionSAP::SAPSetOption(TUint aLevel, TUint aName, const TDesC8& aOption)
       
   372 	{
       
   373 	LOG_FUNC
       
   374 	// Perform a setopt
       
   375 
       
   376 	if (aLevel!=KSolBtL2CAP)
       
   377 		{
       
   378 		// pass down
       
   379 
       
   380 		return iL2CapSAPSignalHandler->SetOption(aLevel, aName, aOption);
       
   381 		}
       
   382 
       
   383 	switch (aName)
       
   384 		{
       
   385 		case KL2CAPRTXTimer:
       
   386 			{
       
   387 			TInt val = *reinterpret_cast<const TInt*>(aOption.Ptr());
       
   388 			if (aOption.Length() != sizeof(TInt) || val < HL2CapCommand::KMinRTXTimerDuration || val > HL2CapCommand::KMaxRTXTimerDuration)
       
   389 				return KErrArgument;
       
   390 			return iL2CapSAPSignalHandler->SetRTXTimerDuration(static_cast<TUint8>(val));
       
   391 			}
       
   392 		case KL2CAPERTXTimer:
       
   393 			{
       
   394 			TInt val = *reinterpret_cast<const TInt*>(aOption.Ptr());
       
   395 			if (aOption.Length() != sizeof(TInt) || val < HL2CapCommand::KMinERTXTimerDuration || val > HL2CapCommand::KMaxERTXTimerDuration)
       
   396 				return KErrArgument;
       
   397 			return iL2CapSAPSignalHandler->SetERTXTimerDuration(static_cast<TUint8>(val));
       
   398 			}
       
   399 		case KL2CAPInboundMTU:
       
   400 			{
       
   401 			TUint16 val = *reinterpret_cast<const TUint16*>(aOption.Ptr());
       
   402 			if (aOption.Length() != sizeof(TUint16) || val < KL2MinMTU)
       
   403 				return KErrArgument;
       
   404 			TL2CapConfig conf;
       
   405 			conf.SetMaxReceiveUnitSize(val);
       
   406 			return iL2CapSAPSignalHandler->UpdateChannelConfig(conf);
       
   407 			}
       
   408 #ifdef _DEBUG
       
   409 		case KL2CAPDebugOptionMask:
       
   410 			{// Set the debug options mask
       
   411 			if (aOption.Length() != sizeof(TUint))
       
   412 				return KErrArgument;
       
   413 			Protocol().iDebugOptionMask = *reinterpret_cast<const TUint*>(aOption.Ptr());
       
   414 			return KErrNone;
       
   415 			}
       
   416 #endif
       
   417 		case KL2CAPNegotiatedOutboundMTU:
       
   418 	    case KL2CAPOutboundMTUForBestPerformance: //equals KL2CAPGetOutboundMTU here for legacy purposes
       
   419 	        {
       
   420 	        TUint16 val = *reinterpret_cast<const TUint16*>(aOption.Ptr());
       
   421 	        if (aOption.Length() != sizeof(TUint16) || val < KL2MinMTU)
       
   422 	            return KErrArgument;
       
   423 			TL2CapConfig conf;
       
   424 			conf.SetMaxTransmitUnitSize(val);
       
   425 			return iL2CapSAPSignalHandler->UpdateChannelConfig(conf);
       
   426 	        }
       
   427 
       
   428 		case KBTSecurityDeviceOverride:
       
   429 			{
       
   430 			return SetDeviceOverride(aOption); 
       
   431 			}
       
   432 
       
   433 		case KL2CAPUpdateChannelConfig:
       
   434 			{
       
   435 			const TL2CapConfig apiConf = *reinterpret_cast<const TL2CapConfig*>(aOption.Ptr());
       
   436 			return iL2CapSAPSignalHandler->UpdateChannelConfig(apiConf);
       
   437 			}
       
   438 			
       
   439 		// Can't set these
       
   440 		default:
       
   441 			return KErrNotSupported;
       
   442 		};
       
   443 	}
       
   444 
       
   445 TInt CL2CAPConnectionSAP::GetOption(TUint aLevel,TUint aName,TDes8& aOption) const
       
   446 	{
       
   447 	LOG_FUNC
       
   448 	if (aLevel!=KSolBtL2CAP)
       
   449 		{// it must be for the lower layers then
       
   450 		
       
   451 		return iL2CapSAPSignalHandler->GetOption(aLevel, aName, aOption);
       
   452 		}
       
   453 
       
   454 	TInt val = 0;
       
   455 	TInt rValue = KErrNone;
       
   456 	
       
   457 	switch (aName)
       
   458 		{
       
   459 		case KL2CAPGetMaxOutboundMTU:
       
   460 			if(aOption.Length() == sizeof(TInt))
       
   461 				{
       
   462 				val = KL2CapMaxMTUSize;
       
   463 				aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
   464 				}
       
   465 			else
       
   466 				{
       
   467 				rValue = KErrArgument;
       
   468 				}
       
   469 			break;
       
   470 			
       
   471 		case KL2CAPGetMaxInboundMTU:
       
   472 			if(aOption.Length() == sizeof(TInt))
       
   473 				{
       
   474 				val = KL2CapMaxMTUSize;
       
   475 				aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
   476 				}
       
   477 			else
       
   478 				{
       
   479 				rValue = KErrArgument;
       
   480 				}
       
   481 			break;
       
   482 			
       
   483 		case KL2CAPNegotiatedOutboundMTU:
       
   484 			if(aOption.Length() == sizeof(TInt))
       
   485 				{
       
   486 				if(iL2CapDataQueue)
       
   487 					{
       
   488 					val = iL2CapDataQueue->MaxOutgoingMTU();
       
   489 					aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
   490 					}
       
   491 				else
       
   492 					{
       
   493 					rValue = KErrNotReady;
       
   494 					}
       
   495 				}
       
   496 			else
       
   497 				{
       
   498 				rValue = KErrArgument;
       
   499 				}
       
   500 			break;	
       
   501 
       
   502 		case KL2CAPOutboundMTUForBestPerformanceWithRestriction:
       
   503 			// get the restriction value
       
   504 			if((aOption.Length() == sizeof(TInt)) && iL2CapDataQueue && iL2CapSAPSignalHandler)
       
   505 				{
       
   506 				val = *reinterpret_cast<const TInt*>(aOption.Ptr());
       
   507 
       
   508 				// Ensure that the restriction is less then the current MTU.
       
   509 				if (val < iL2CapDataQueue->MaxOutgoingMTU())
       
   510 					{
       
   511 					// We now need to recalculate the optimal PDU size for the restricted MTU as
       
   512 					// this is used in the calculation of the optimal MTU
       
   513 					TPckgBuf<TInt> buf;	
       
   514 					TInt err = iL2CapSAPSignalHandler->GetOption(KSolBtACL, ELMOutboundACLSize, buf);
       
   515 
       
   516 					TInt optimalPduSize = HL2CapPDU::GetPDUOrFragmentSize(val, iL2CapDataQueue->MaximumPDUSize(), (err == KErrNone) ? buf() : 0, iL2CapDataQueue->IsBasicDataVersion());
       
   517 
       
   518 					// update the data queue to use the new optimal PDU size from now on
       
   519 					iL2CapDataQueue->SetOptimalPDUSize(optimalPduSize);
       
   520 					}
       
   521 				else
       
   522 					{
       
   523 					// can't increase the MTU at this stage so just use the existing MTU
       
   524 					val = iL2CapDataQueue->MaxOutgoingMTU();
       
   525 					}
       
   526 
       
   527 				// work out the optimal MTU
       
   528 				val = GetOptimalMTUSize(val, iL2CapDataQueue->OptimalPDUSize(), iL2CapDataQueue->IsBasicDataVersion());
       
   529 				aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
   530 				}			
       
   531 			break;
       
   532 
       
   533 		case KL2CAPOutboundMTUForBestPerformance: //equals KL2CAPGetOutboundMTU
       
   534 			if(aOption.Length() == sizeof(TInt))
       
   535 				{
       
   536 				if(iL2CapDataQueue && iL2CapSAPSignalHandler)
       
   537 					{
       
   538 					// work out the optimal MTU
       
   539 					val = GetOptimalMTUSize(iL2CapDataQueue->MaxOutgoingMTU(), iL2CapDataQueue->OptimalPDUSize(), iL2CapDataQueue->IsBasicDataVersion());
       
   540 					aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
   541 					}
       
   542 				else
       
   543 					{
       
   544 					rValue = KErrNotReady;
       
   545 					}
       
   546 				}
       
   547 			else
       
   548 				{
       
   549 				rValue = KErrArgument;
       
   550 				}
       
   551 			break;	
       
   552 			
       
   553 		case KL2CAPInboundMTU:
       
   554 			if(aOption.Length() == sizeof(TInt))
       
   555 				{
       
   556 				if(iL2CapDataQueue)
       
   557 					{
       
   558 					val = iL2CapDataQueue->MaxIncomingMTU();
       
   559 					aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
   560 					}
       
   561 				else
       
   562 					{
       
   563 					rValue = KErrNotReady;
       
   564 					}
       
   565 				}
       
   566 			else
       
   567 				{
       
   568 				rValue = KErrArgument;
       
   569 				}
       
   570 			break;	
       
   571 
       
   572 		case KL2CAPRTXTimer:
       
   573 			if(aOption.Length() == sizeof(TInt))
       
   574 				{
       
   575 				val = iL2CapSAPSignalHandler->RTXTimerDuration();
       
   576 				aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
   577 				}
       
   578 			else
       
   579 				{
       
   580 				rValue = KErrArgument;
       
   581 				}
       
   582 			break;
       
   583 
       
   584 		case KL2CAPERTXTimer:
       
   585 			if(aOption.Length() == sizeof(TInt))
       
   586 				{
       
   587 				val = iL2CapSAPSignalHandler->ERTXTimerDuration();
       
   588 				aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
   589 				}
       
   590 			else
       
   591 				{
       
   592 				rValue = KErrArgument;
       
   593 				}
       
   594 			break;
       
   595 
       
   596 		case KBTSecurityDeviceOverride:
       
   597 			// aspect oriented programming would be nice.
       
   598 			rValue = GetDeviceOverride(aOption); 
       
   599 			break;
       
   600 			
       
   601 		case KL2CAPGetDebug1:
       
   602 			val = static_cast<TInt>((static_cast<SBtTls*>(Dll::Tls()))->iPort);
       
   603 			aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
   604 			break;
       
   605 			
       
   606 		// returns the PSM for the accepted SAP (or listening SAP if clients forgot)
       
   607 		case KL2CAPLocalPSM:
       
   608 			{
       
   609 			if (aOption.Length() == sizeof(TL2CAPPort))
       
   610 				{
       
   611 				const CL2CAPConnectionSAP* listeningSAP = ListeningSAP();
       
   612 				if (!listeningSAP)
       
   613 					{
       
   614 					listeningSAP = this;
       
   615 					}
       
   616 				TL2CAPSockAddr locAddr;
       
   617 				listeningSAP->LocalName(locAddr);
       
   618 				TPckg<TL2CAPPort> pckg(locAddr.Port());
       
   619 				aOption = pckg;
       
   620 				}
       
   621 			else
       
   622 				{
       
   623 				rValue = KErrArgument;
       
   624 				}
       
   625 			}
       
   626 			break;
       
   627 
       
   628 		// Returns the negotiated channel mode.
       
   629 		// KErrNotReady if the channel hasn't undergone configuration yet. 
       
   630 		case KL2CAPNegotiatedChannelMode:
       
   631 			if(aOption.Length() == sizeof(TL2CapChannelMode))
       
   632 				{
       
   633 				TL2CapChannelMode mode;
       
   634 				rValue = iL2CapSAPSignalHandler->GetNegotiatedChannelMode(mode);
       
   635 				TPckgBuf<TL2CapChannelMode> pckg(mode);
       
   636 				aOption = pckg;
       
   637 				}
       
   638 			else
       
   639 				{
       
   640 				rValue = KErrArgument;
       
   641 				}
       
   642 			break;
       
   643 
       
   644 #ifdef _DEBUG
       
   645 
       
   646 		case KL2CAPVersion1_2:
       
   647 			// This debug option is used to check if the stack is a 1.2 version.
       
   648 			// For pre 1.2 versions the stack will respond with KErrNotSupported.
       
   649 			break;
       
   650 						
       
   651 		case KL2CAPHeapAlloc:
       
   652 			if(aOption.Length() == sizeof(TInt))
       
   653 				{
       
   654 				val = User::Heap().Count();
       
   655 				aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
   656 				}
       
   657 			else
       
   658 				{
       
   659 				rValue = KErrArgument;
       
   660 				}
       
   661 			break;
       
   662 			
       
   663 		case KL2CAPDataPlaneConfig:
       
   664 			{	
       
   665 			if(iL2CapDataQueue)
       
   666 				{
       
   667 				TL2DataPlaneConfig conf;
       
   668 				iL2CapDataQueue->GetDataPlaneConfig(conf);
       
   669 				TL2DataPlaneConfigPkg pckg(conf);
       
   670 				aOption = pckg;
       
   671 				}
       
   672 			else
       
   673 				{
       
   674 				rValue = KErrNotReady;
       
   675 				}
       
   676 			}
       
   677 			break;
       
   678 		
       
   679 #endif
       
   680 			
       
   681 		default:
       
   682 			rValue = KErrNotSupported;
       
   683 			break;
       
   684 		};
       
   685 	return rValue;	
       
   686 	}
       
   687 
       
   688 
       
   689 void CL2CAPConnectionSAP::Ioctl(TUint aLevel,TUint aName,TDes8* aOption)
       
   690 /** 
       
   691 	Handle an Ioctl from above. 
       
   692 	
       
   693 	Some Ioctls are not for L2CAP but must be handled here anyway.
       
   694 	Other non-L2CAP Ioctls should just be passed downward.
       
   695 
       
   696 	If the Ioctl is for L2CAP and should be handled the same in all states, 
       
   697 	then handle it here, otherwise, pass it on to the current state.
       
   698 
       
   699 	@param aLevel		Level of Ioctl (should be KSolBtL2CAP here)
       
   700 	@param aName		Name of Ioctl
       
   701 	@param aOption		Ioctl data
       
   702 **/
       
   703 	{
       
   704 	LOG_FUNC
       
   705 	__ASSERT_DEBUG(iOutstandingIoctlName == 0, Panic(EL2SAPTwoIoctls));
       
   706 
       
   707 	// Must set this first, in case any synchronous errors come up. 	
       
   708 	iOutstandingIoctlName = aName;
       
   709 	TInt rerr = KErrNotSupported;
       
   710 
       
   711 	if(aLevel == KSolBtL2CAP)
       
   712 		{
       
   713 		switch(aName)
       
   714 			{
       
   715 			case KL2CAPEchoRequestIoctl:
       
   716 				rerr = iL2CapSAPSignalHandler->SendEchoRequest(aOption);
       
   717 				break;
       
   718 
       
   719 			case KL2CAPIncomingMTUIoctl:
       
   720 				{
       
   721 				const TUint8* optionPtr = aOption->Ptr();
       
   722 				TUint16 newSize = *((TUint16*)optionPtr);
       
   723 				TL2CapConfig conf;
       
   724 				conf.SetMaxReceiveUnitSize(newSize);
       
   725 				rerr = iL2CapSAPSignalHandler->UpdateChannelConfig(conf);
       
   726 			  	if(rerr == KErrNone)
       
   727 					{
       
   728 					// The operation has completed.   
       
   729 					IoctlComplete(KErrNone, KSolBtL2CAP, KL2CAPIncomingMTUIoctl, aOption);
       
   730 					rerr = KErrNone;
       
   731 					}
       
   732 				else
       
   733 					{
       
   734 					if(rerr == KErrL2CAPConfigPending)
       
   735 						{
       
   736 						// This indicates that configuration is pending.
       
   737 						rerr = KErrNone;
       
   738 						}
       
   739 					}
       
   740 				}
       
   741 				break;
       
   742 				
       
   743 			case KL2CAPOutgoingMTUIoctl:
       
   744 				{
       
   745 				const TUint8* optionPtr = aOption->Ptr();
       
   746 				TUint16 newSize = *((TUint16*)optionPtr);
       
   747 				TL2CapConfig conf;
       
   748 				conf.SetMaxTransmitUnitSize(newSize);
       
   749 				rerr = iL2CapSAPSignalHandler->UpdateChannelConfig(conf);
       
   750 			  	if(rerr == KErrNone)
       
   751 					{
       
   752 					// The operation has completed.   
       
   753 					IoctlComplete(KErrNone, KSolBtL2CAP, KL2CAPOutgoingMTUIoctl, aOption);
       
   754 					rerr = KErrNone;
       
   755 					}
       
   756 				else
       
   757 					{
       
   758 					if(rerr == KErrL2CAPConfigPending)
       
   759 						{
       
   760 						// This indicates that configuration is pending.
       
   761 						rerr = KErrNone;
       
   762 						}
       
   763 					}
       
   764 				}
       
   765 				break;
       
   766 
       
   767 			case KL2CAPUpdateChannelConfigIoctl:
       
   768 				{
       
   769 				const TL2CapConfig* conf = reinterpret_cast<const TL2CapConfig*>(aOption->Ptr());
       
   770 				rerr = UpdateChannelConfig(*conf);
       
   771 			  	if(rerr == KErrNone)
       
   772 					{
       
   773 					// The operation has completed.   
       
   774 					IoctlComplete(KErrNone, KSolBtL2CAP, KL2CAPUpdateChannelConfigIoctl, aOption);
       
   775 					rerr = KErrNone;
       
   776 					}
       
   777 				else
       
   778 					{
       
   779 					if(rerr == KErrL2CAPConfigPending)
       
   780 						{
       
   781 						// This indicates that configuration is pending.
       
   782 						rerr = KErrNone;
       
   783 						}
       
   784 					}
       
   785 				}
       
   786 				break;
       
   787 
       
   788 			case KL2CAPPretendIncomingSduQFull:
       
   789 				{
       
   790 #ifdef _DEBUG
       
   791 				if (aOption && aOption->Length() == sizeof(TBool))
       
   792 					{
       
   793 					iL2CapDataQueue->PretendIncomingSduQFull(*reinterpret_cast<const TBool*>(aOption->Ptr()));
       
   794 					IoctlComplete(KErrNone, KSolBtL2CAP, KL2CAPPretendIncomingSduQFull, aOption);
       
   795 					rerr = KErrNone;
       
   796 					}
       
   797 				else
       
   798 					{
       
   799 					rerr = KErrArgument;
       
   800 					}
       
   801 #endif
       
   802 				}
       
   803 				// Return not supported in UREL.
       
   804 				break;
       
   805 
       
   806 			default:
       
   807 				// Return not supported.
       
   808 				break;
       
   809 			}
       
   810 		}
       
   811 
       
   812 	if (rerr != KErrNone)
       
   813 		{
       
   814 		iOutstandingIoctlName = 0;
       
   815 		iSocket->Error(rerr, MSocketNotify::EErrorIoctl);
       
   816 		}
       
   817 	}
       
   818 
       
   819 #ifdef _DEBUG
       
   820 void CL2CAPConnectionSAP::CancelIoctl(TUint aLevel, TUint aName)
       
   821 #else
       
   822 void CL2CAPConnectionSAP::CancelIoctl(TUint /*aLevel*/, TUint /*aName*/)
       
   823 #endif
       
   824 	{
       
   825 	LOG_FUNC
       
   826 	__ASSERT_DEBUG((aLevel == KSolBtL2CAP && aName == iOutstandingIoctlName), Panic(EL2SAPStrayIoctlCancel));
       
   827 	iOutstandingIoctlName = 0;
       
   828 	}
       
   829 
       
   830 void CL2CAPConnectionSAP::IoctlComplete(TInt aErr, TUint aLevel, TUint aName, TDesC8* aBuf)
       
   831 	{
       
   832 	LOG_FUNC
       
   833 	if(aLevel == KSolBtL2CAP && aName == iOutstandingIoctlName)
       
   834 		{
       
   835 		if(aErr == KErrNone)
       
   836 			{
       
   837 			if(iSocket)
       
   838 				{
       
   839 				iSocket->IoctlComplete(aBuf);
       
   840 				}
       
   841 			}
       
   842 		else
       
   843 			{
       
   844 			iSocket->Error(aErr, MSocketNotify::EErrorIoctl);
       
   845 			}
       
   846 		iOutstandingIoctlName = 0;
       
   847 		}
       
   848 	}
       
   849 
       
   850 void CL2CAPConnectionSAP::EchoResponseReceived(const TDesC8* aData)
       
   851 	{
       
   852 	LOG_FUNC
       
   853 	TDesC8* data = const_cast<TDesC8*>(aData);
       
   854 	IoctlComplete(KErrNone, KSolBtL2CAP, KL2CAPEchoRequestIoctl, data);
       
   855 	}
       
   856 
       
   857 
       
   858 void CL2CAPConnectionSAP::Start()
       
   859 	{
       
   860 	LOG_FUNC
       
   861 	// Called when data's about to flow
       
   862 
       
   863 	iAcceptPending = EFalse;
       
   864 	iState->Start(*this);
       
   865 	}
       
   866 
       
   867 
       
   868 void CL2CAPConnectionSAP::ActiveOpen()
       
   869 	{
       
   870 	LOG_FUNC
       
   871 	// Setup the link
       
   872 
       
   873 	iState->ActiveOpen(*this);
       
   874 	}
       
   875 
       
   876 void CL2CAPConnectionSAP::ActiveOpen(const TDesC8& /*aConnectionData*/)
       
   877 	{
       
   878 	LOG_FUNC
       
   879 	// This is an error
       
   880 	Panic(EL2CAPSAPOpenWithConnectionDataNotSupported);
       
   881 	}
       
   882 
       
   883 TInt CL2CAPConnectionSAP::PassiveOpen(TUint aQueSize)
       
   884 	{
       
   885 	LOG_FUNC
       
   886 	// A Listen request
       
   887 	// Now a listening SAP has been opened, start the underlying protocol listening.
       
   888 	return iState->PassiveOpen(*this, aQueSize);
       
   889 	}
       
   890 
       
   891 TInt CL2CAPConnectionSAP::PassiveOpen(TUint /*aQueSize*/, const TDesC8& /*aConnectionData*/)
       
   892 	{
       
   893 	LOG_FUNC
       
   894 	// This operation is not currently supported.
       
   895 	Panic(EL2CAPSAPOpenWithConnectionDataNotSupported);
       
   896 	return KErrNotSupported;
       
   897 	}
       
   898 
       
   899 void CL2CAPConnectionSAP::Shutdown(TCloseType aOption)
       
   900 	{
       
   901 	LOG_FUNC
       
   902 	LOG2(_L("L2CAP [l2sap.cpp]: CL2CAPConnectionSAP::Shutdown, option = %d, SAP %08x"), aOption, this);
       
   903 	// Shutdown
       
   904 	if(aOption != EImmediate)
       
   905 		{
       
   906 		// Normal shutdown, ESOCK will wait for the SAP to signal Can Close.
       
   907 		iShutdownReceived = ESAPShutdownNormal;
       
   908 		iState->Shutdown(*this);
       
   909 		}
       
   910 	else
       
   911 		{
       
   912 		iShutdownReceived = ESAPShutdownImmediate;
       
   913 		iState->FastShutdown(*this);
       
   914 		}
       
   915 	}
       
   916 
       
   917 void CL2CAPConnectionSAP::Shutdown(TCloseType /*option*/, 
       
   918 								   const TDesC8& /*aDisconnectionData*/)
       
   919 	{
       
   920 	LOG_FUNC
       
   921 	// this one's an error
       
   922 	Panic(EL2CAPShutdownWithDisconnectionDataNotSupported);
       
   923 	}
       
   924 
       
   925 void CL2CAPConnectionSAP::AutoBind()
       
   926 /**
       
   927 	Auto bind from esock.
       
   928 	Do nothing -- as we always allocate a local CID
       
   929 	in ActiveConnect anyway.
       
   930 **/
       
   931 	{
       
   932 	LOG_FUNC
       
   933 	}
       
   934 
       
   935 
       
   936 TInt CL2CAPConnectionSAP::Write(RMBufChain& aData, TUint aOptions, TSockAddr* /*anAddr*/)
       
   937 	{
       
   938 	LOG_FUNC
       
   939 	// If the write completes without error return 1.  
       
   940 	// If not the definition [of the return parameter
       
   941 	// of this method] in CServProviderBase indicates that zero
       
   942 	// should be returned.
       
   943 	TInt err = iState->Send(*this, aData, aOptions);
       
   944 	// If there is an error then simply returning 0 will just "flow off"
       
   945 	// esock (i.e. the write won't be completed).  We are reliant on
       
   946 	// some other event to either error the send or disconnect in order
       
   947 	// to complete the request.
       
   948 	return (err == KErrNone ? 1 : 0);
       
   949 	}
       
   950 
       
   951 TInt CL2CAPConnectionSAP::GetData(RMBufChain& aData, TUint /*aLength*/, TUint /*aOptions*/, TSockAddr* /*anAddr*/)
       
   952 	{
       
   953 	LOG_FUNC
       
   954 	return iState->Read(*this, aData);
       
   955 	}
       
   956 
       
   957 TUint CL2CAPConnectionSAP::Write(const TDesC8& aDesc, TUint aOptions, TSockAddr* /*anAddr*/)
       
   958 	{
       
   959 	LOG_FUNC
       
   960 	// Temporary Shim.  Should be remove when no longer used.
       
   961 	RMBufChain buf;
       
   962 	TInt err = KErrNone;
       
   963 	
       
   964 	// A zero return value indicates that no data was sent.
       
   965 	TUint rValue = 0;
       
   966 	
       
   967 	TRAP(err, buf.CreateL(aDesc));
       
   968 	if(err == KErrNone)
       
   969 		{
       
   970 		rValue = Write(buf, aOptions);
       
   971 		}
       
   972 
       
   973 	buf.Free();
       
   974 	return rValue;
       
   975 	}
       
   976 
       
   977 void CL2CAPConnectionSAP::GetData(TDes8& aDesc, TUint aOptions, TSockAddr* anAddr)
       
   978 	{
       
   979 	LOG_FUNC
       
   980 	// Temporary Shim.  Should be remove when no longer used.
       
   981 	RMBufChain buf;
       
   982 	GetData(buf, 0, aOptions, anAddr);
       
   983 	buf.CopyOut(aDesc);
       
   984 	buf.Free();
       
   985 	}
       
   986 	
       
   987 
       
   988 // Methods from SAP Signal Handler
       
   989 void CL2CAPConnectionSAP::LinkUp()
       
   990 	{
       
   991 	LOG_FUNC
       
   992 	iState->LinkUp(*this);
       
   993 	}
       
   994 
       
   995 void CL2CAPConnectionSAP::ChannelOpened()
       
   996 	{
       
   997 	LOG_FUNC
       
   998 	iState->ChannelOpened(*this);
       
   999 	}
       
  1000 
       
  1001 void CL2CAPConnectionSAP::ChannelConfigured(CL2CapChannelConfig& aConfig,
       
  1002                                             CL2CAPMux& aMuxer,
       
  1003                                             TL2CAPPort aLocalPort,
       
  1004                                             TL2CAPPort aRemotePort)
       
  1005 	{
       
  1006 	LOG_FUNC
       
  1007 	iState->ChannelConfigured(*this, aConfig, aMuxer, aLocalPort, aRemotePort);
       
  1008 	}
       
  1009 
       
  1010 void CL2CAPConnectionSAP::ReconfiguringChannel()
       
  1011 	{
       
  1012 	LOG_FUNC
       
  1013 	iState->ReconfiguringChannel(*this);
       
  1014 	}
       
  1015 	
       
  1016 void CL2CAPConnectionSAP::ChannelClosed()
       
  1017 	{
       
  1018 	LOG_FUNC
       
  1019 	iState->ChannelClosed(*this);
       
  1020 	}
       
  1021 
       
  1022 void CL2CAPConnectionSAP::DataPlaneError(TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction)
       
  1023 	{
       
  1024 	LOG_FUNC
       
  1025 	iState->DataPlaneError(*this, aErrorCode, aErrorAction);
       
  1026 	}
       
  1027 
       
  1028 void CL2CAPConnectionSAP::SignalHandlerError(TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction)
       
  1029 	{
       
  1030 	LOG_FUNC
       
  1031 	iState->SignalHandlerError(*this, aErrorCode, aErrorAction);
       
  1032 	}
       
  1033 	
       
  1034 
       
  1035 // Methods from Data Controller
       
  1036 void CL2CAPConnectionSAP::NewData()
       
  1037 	{
       
  1038 	LOG_FUNC
       
  1039 	iState->NewData(*this);
       
  1040 	}
       
  1041 	
       
  1042 void CL2CAPConnectionSAP::CanSend()
       
  1043 	{
       
  1044 	LOG_FUNC
       
  1045 	iState->CanSend(*this);
       
  1046 	}
       
  1047 
       
  1048 void CL2CAPConnectionSAP::CloseOutgoingSDUQueue()
       
  1049 	{
       
  1050 	LOG_FUNC
       
  1051 	iState->CloseOutgoingSDUQueue(*this);
       
  1052 	}
       
  1053 	
       
  1054 void CL2CAPConnectionSAP::SDUQueueClosed()
       
  1055 	{
       
  1056 	LOG_FUNC
       
  1057 	// Delete the SDU queue.
       
  1058 	delete iL2CapDataQueue;
       
  1059 	iL2CapDataQueue = NULL;
       
  1060 	
       
  1061 	// Inform the state that the data plane is closed.
       
  1062 	iState->SDUQueueClosed(*this);	
       
  1063 	}	
       
  1064 
       
  1065 void CL2CAPConnectionSAP::SetState(TL2CAPSAPState& aState)
       
  1066 	{
       
  1067 	LOG_FUNC
       
  1068 	iState->Exit(*this);
       
  1069 	iState = &aState;
       
  1070 	iState->Enter(*this);
       
  1071 	}
       
  1072 
       
  1073 TInt CL2CAPConnectionSAP::CreateDataPlane(CL2CapChannelConfig& aConfig, 
       
  1074                                           CL2CAPMux& aMuxer,
       
  1075                                           TL2CAPPort aLocalPort,
       
  1076                                           TL2CAPPort aRemotePort)
       
  1077 	{
       
  1078 	LOG_FUNC
       
  1079 	TInt rerr = KErrNone;
       
  1080 	const TL2CapFecNegotiator& fec = aConfig.FecNegotiator();
       
  1081 	TL2CapDataControllerConfig* dataConfig = new TL2CapDataControllerConfig(fec.DataControllerConfig());
       
  1082 
       
  1083 	if(dataConfig)
       
  1084 		{
       
  1085 		TRAP(rerr, iL2CapDataQueue = CL2CapSDUQueue::NewL(*this,
       
  1086 		                                                  aLocalPort,
       
  1087 		                                                  aRemotePort,
       
  1088 		                                                  aMuxer,
       
  1089 					                       				  fec.OutgoingMaximumPDUSize(),
       
  1090 		                                                  CL2CapSDUQueue::KDefaultOutboundQueueSize,
       
  1091 		                       			            	  dataConfig,
       
  1092 											   			  aConfig.OutgoingFlushTimeout().Negotiated().FlushTimeoutDuration(),
       
  1093 					                       				  aConfig.OutgoingMTU().Negotiated().MTU(),
       
  1094 					                       				  aConfig.IncomingMTU().Negotiated().MTU(),
       
  1095 					                       				  // Allow ourselves to drop SDUs we can't assemble if channel mode is not Reliable.
       
  1096 					                       				  !TRetransmissionAndFlowControlOption::IsModeReliable(fec.IncomingLinkMode())));
       
  1097 
       
  1098 		// Set the optimal PDU size that the data controller should use.
       
  1099 		TPckgBuf<TInt> buf;	
       
  1100 		TInt err = iL2CapSAPSignalHandler->GetOption(KSolBtACL, ELMOutboundACLSize, buf);
       
  1101 
       
  1102 		TInt optimalPduSize = HL2CapPDU::GetPDUOrFragmentSize(iL2CapDataQueue->MaxOutgoingMTU(), iL2CapDataQueue->MaximumPDUSize(), (err == KErrNone) ? buf() : 0, iL2CapDataQueue->IsBasicDataVersion());
       
  1103 		iL2CapDataQueue->SetOptimalPDUSize(optimalPduSize);
       
  1104 		}
       
  1105 	else
       
  1106 		{
       
  1107 		rerr = KErrNoMemory;
       
  1108 		}
       
  1109 
       
  1110 	return rerr;
       
  1111 	}
       
  1112 	
       
  1113 
       
  1114 void CL2CAPConnectionSAP::PauseDataPlane()
       
  1115 	{
       
  1116 	LOG_FUNC
       
  1117 	__ASSERT_DEBUG(iL2CapDataQueue, Panic(EL2CAPPauseDataPlaneCalledWhenDataPlaneDoesNotExist));
       
  1118 	iL2CapDataQueue->SuspendSDUQueue();				
       
  1119 	}
       
  1120 
       
  1121 void CL2CAPConnectionSAP::TryToCompleteConfigurationIoctl(TInt aError)
       
  1122 	{
       
  1123 	LOG_FUNC
       
  1124 	switch(iOutstandingIoctlName)
       
  1125 		{
       
  1126 		case KL2CAPIncomingMTUIoctl:
       
  1127 		case KL2CAPOutgoingMTUIoctl:
       
  1128 		case KL2CAPUpdateChannelConfigIoctl:
       
  1129 			if(aError == KErrNone)
       
  1130 				{
       
  1131 				IoctlComplete(KErrNone, KSolBtL2CAP, iOutstandingIoctlName, NULL);
       
  1132 				}
       
  1133 			else
       
  1134 				{
       
  1135 				iSocket->Error(aError, MSocketNotify::EErrorIoctl);
       
  1136 				}
       
  1137 			iOutstandingIoctlName = 0;
       
  1138 			break;
       
  1139 			
       
  1140 		default:
       
  1141 			break;
       
  1142 		};
       
  1143 	}
       
  1144 	
       
  1145 void CL2CAPConnectionSAP::AccessRequestComplete(TInt aResult)
       
  1146 	{
       
  1147 	LOG_FUNC
       
  1148 	iState->AccessRequestComplete(*this, aResult);
       
  1149 	}
       
  1150 
       
  1151 TInt CL2CAPConnectionSAP::UpdateChannelConfig(const TL2CapConfig& aAPIConfig)
       
  1152 	{
       
  1153 	LOG_FUNC
       
  1154 	TInt rerr = KErrNone;
       
  1155 	if(iL2CapSAPSignalHandler)
       
  1156 		{
       
  1157 		// Update the channel config.
       
  1158 		rerr = iL2CapSAPSignalHandler->UpdateChannelConfig(aAPIConfig);
       
  1159 
       
  1160 		// Check if the a new priority has been specified.
       
  1161 		TBool specified;
       
  1162 		TUint8 newPriority = static_cast<TUint8>(aAPIConfig.ChannelPriority(specified));
       
  1163 		if(specified && iChannelPriority != newPriority)
       
  1164 			{
       
  1165 			iChannelPriority = newPriority;
       
  1166 			if(iL2CapDataQueue)
       
  1167 				{
       
  1168 				iL2CapDataQueue->UpdateChannelPriority(iChannelPriority);
       
  1169 				}
       
  1170 			}
       
  1171 		}
       
  1172 	else
       
  1173 		{
       
  1174 		rerr = KErrNotReady;
       
  1175 		}
       
  1176 	return rerr;
       
  1177 	}
       
  1178 	
       
  1179 void CL2CAPConnectionSAP::DetachFromListeningSAP()
       
  1180 	{
       
  1181 	LOG_FUNC
       
  1182 	if(iListeningSAP)
       
  1183 		{
       
  1184 		iListeningSAP->DequeClone(this);
       
  1185 		iListeningSAP = NULL;
       
  1186 		}
       
  1187 	}