bluetooth/btstack/linkmgr/ACLSAP.cpp
changeset 0 29b1cd4cb562
child 8 2b6718f05bdb
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2003-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 // ACL.cpp
       
    15 // Implementation of ACL Logical links
       
    16 // 
       
    17 //
       
    18 
       
    19 #include <bluetooth/logger.h>
       
    20 #include <bt_sock.h>
       
    21 #include <bluetooth/hci/aclpacketconsts.h>
       
    22 
       
    23 #include "ACLSAP.h"
       
    24 #include "physicallinks.h"
       
    25 #include "physicallinksmanager.h"
       
    26 #include "Basebandmodel.h"
       
    27 #include "linkmgr.h"
       
    28 #include "AclDataQController.h"
       
    29 #include "linkconsts.h"
       
    30 #include "linkutil.h"
       
    31 
       
    32 #include "hcifacade.h"
       
    33 
       
    34 #ifdef __FLOG_ACTIVE
       
    35 _LIT8(KLogComponent, LOG_COMPONENT_LINKMGR);
       
    36 #endif
       
    37 
       
    38 #pragma warning (disable: 4100) //unreference formal param
       
    39 
       
    40 CACLLinkStateFactory* CACLLinkStateFactory::NewL()
       
    41 	{
       
    42 	LOG_STATIC_FUNC
       
    43 	CACLLinkStateFactory* ret=new (ELeave) CACLLinkStateFactory();
       
    44 	CleanupStack::PushL(ret);
       
    45 	ret->ConstructL();
       
    46 	CleanupStack::Pop(ret);
       
    47 	return ret;
       
    48 	}
       
    49 
       
    50 void CACLLinkStateFactory::ConstructL()
       
    51 	{
       
    52 	LOG_FUNC
       
    53 	iStates[EClosed]				=new (ELeave) TACLLinkStateClosed(*this);
       
    54 	iStates[EListening]				=new (ELeave) TACLLinkStateListening(*this);
       
    55 	iStates[EAccepting]				=new (ELeave) TACLLinkStateAccepting(*this);
       
    56 	iStates[EWaitForLink]			=new (ELeave) TACLLinkStateWaitForLink(*this);
       
    57 	iStates[EWaitForStart]			=new (ELeave) TACLLinkStateWaitForStart(*this);
       
    58 	iStates[EWaitForStartError]		=new (ELeave) TACLLinkStateWaitForStartError(*this);
       
    59 	iStates[EWaitForStartParked]	=new (ELeave) TACLLinkStateWaitForStartParked(*this);
       
    60 	iStates[EOpen]					=new (ELeave) TACLLinkStateOpen(*this);
       
    61 	iStates[EOpenParked]			=new (ELeave) TACLLinkStateOpenParked(*this);
       
    62 	iStates[EClosing]				=new (ELeave) TACLLinkStateClosing(*this);
       
    63 	}
       
    64 
       
    65 CACLLinkStateFactory::~CACLLinkStateFactory()
       
    66 	{
       
    67 	LOG_FUNC
       
    68 	iStates.DeleteAll();
       
    69 	}
       
    70 
       
    71 TACLLinkState& CACLLinkStateFactory::GetState(CACLLinkStateFactory::TACLLinkStates aState)
       
    72 	{
       
    73 	LOG_FUNC
       
    74 	__ASSERT_DEBUG(aState != EACLLinkMaxState, Panic(EACLLinkStateOutOfBounds));
       
    75 	return *iStates[aState];
       
    76 	}
       
    77 
       
    78 TInt CACLLinkStateFactory::StateIndex(const TACLLinkState* aState) const
       
    79 	{
       
    80 	LOG_FUNC
       
    81 	TInt state;
       
    82 	for (state = 0; state < EACLLinkMaxState; state++)
       
    83 		{
       
    84 		if (iStates[state] == aState)
       
    85 			{
       
    86 			return state;
       
    87 			}
       
    88 		}
       
    89 	
       
    90 	return KUnknownState;
       
    91 	}
       
    92 
       
    93 TACLLinkState::TACLLinkState(CACLLinkStateFactory& aFactory)
       
    94 : iFactory(aFactory)
       
    95 	{
       
    96 	LOG_FUNC
       
    97 	}
       
    98 	
       
    99 void TACLLinkState::PanicInState(TLinkPanic aPanic) const
       
   100 	{
       
   101 	LOG_FUNC
       
   102 	Panic(aPanic, iFactory.StateIndex(this));
       
   103 	}
       
   104 
       
   105 void TACLLinkState::ChangeState(CACLLink& aContext, CACLLinkStateFactory::TACLLinkStates aState) const
       
   106 	{
       
   107 	LOG_FUNC
       
   108 	aContext.iState->Exit(aContext);
       
   109 
       
   110 #ifdef __FLOG_ACTIVE
       
   111 	TACLLinkState* state=&iFactory.GetState(aState);
       
   112 	LOG2(_L("ACLLink: State %S -> %S"), &aContext.iState->iName, &state->iName);
       
   113 #endif //__FLOG_ACTIVE
       
   114 	aContext.iState=&iFactory.GetState(aState);
       
   115 
       
   116 	aContext.iState->Enter(aContext);
       
   117 	}
       
   118 
       
   119 
       
   120 void TACLLinkState::Enter(CACLLink& /*aContext*/) const
       
   121 	{
       
   122 	LOG_FUNC
       
   123 	// do nothing
       
   124 	}
       
   125 
       
   126 void TACLLinkState::Exit(CACLLink& /*aContext*/) const
       
   127 	{
       
   128 	LOG_FUNC
       
   129 	// do nothing
       
   130 	}
       
   131 
       
   132 void TACLLinkState::Deletion(CACLLink& /*aContext*/) const
       
   133 	{
       
   134 	LOG_FUNC
       
   135 	PanicInState(EBTACLSAPUnexpectedEvent);
       
   136 	}
       
   137 
       
   138 void TACLLinkState::ActiveOpen(CACLLink& /*aContext*/) const
       
   139 	{
       
   140 	LOG_FUNC
       
   141 	PanicInState(EBTACLSAPUnexpectedEvent);
       
   142 	}
       
   143 
       
   144 void TACLLinkState::DataReceived(CACLLink& /*aContext*/, TUint8 /*aFlag*/, const TDesC8& /*aData*/) const
       
   145 	{
       
   146 	LOG_FUNC
       
   147 	__DEBUGGER(); // drop, but see why went wrong
       
   148 	}
       
   149 
       
   150 void TACLLinkState::Start(CACLLink& /*aContext*/) const
       
   151 	{
       
   152 	LOG_FUNC
       
   153 	PanicInState(EBTACLSAPUnexpectedEvent); //Panics since ESOCK and our state machine might be out of sync
       
   154 	}
       
   155 
       
   156 void TACLLinkState::ConnectComplete(CACLLink& /*aContext*/, const TBTConnect& /*aConnect*/) const
       
   157 	{
       
   158 	LOG_FUNC
       
   159 	//Drop the event silently in UREL
       
   160  	#ifdef _DEBUG
       
   161 	PanicInState(EBTACLSAPUnexpectedEvent);
       
   162 	#endif
       
   163 	}
       
   164 
       
   165 TBool TACLLinkState::ConnectRequest(CACLLink& /*aContext*/,
       
   166 									  const TBTConnect& /*aConnectDetails*/,
       
   167 									  const CPhysicalLink& /*aPhysicalLink*/) const
       
   168 	{
       
   169 	LOG_FUNC
       
   170 	PanicInState(EBTACLSAPUnexpectedEvent);
       
   171 	return EFalse;
       
   172 	}
       
   173 
       
   174 void TACLLinkState::Disconnection(CACLLink& /*aContext*/) const
       
   175 	{
       
   176 	LOG_FUNC
       
   177 	PanicInState(EBTACLSAPUnexpectedEvent);
       
   178 	}
       
   179 
       
   180 void TACLLinkState::Error(CACLLink& /*aContext*/, TInt /*aError*/) const
       
   181 	{
       
   182 	LOG_FUNC
       
   183 	PanicInState(EBTACLSAPUnexpectedEvent);
       
   184 	}
       
   185 
       
   186 void TACLLinkState::Timeout(CACLLink& /*aContext*/, TBasebandTimeout /*aTimeout*/) const
       
   187 	{
       
   188 	LOG_FUNC
       
   189 	PanicInState(EBTACLSAPUnexpectedEvent);
       
   190 	}
       
   191 
       
   192 void TACLLinkState::Shutdown(CACLLink& /*aContext*/, CServProviderBase::TCloseType /*aCloseType*/) const
       
   193 	{
       
   194 	LOG_FUNC
       
   195 	PanicInState(EBTACLSAPUnexpectedEvent);
       
   196 	}
       
   197 
       
   198 TInt TACLLinkState::PassiveOpen(CACLLink& /*aContext*/, TUint /*aQueSize*/) const
       
   199 	{
       
   200 	LOG_FUNC
       
   201 	PanicInState(EBTACLSAPUnexpectedEvent);
       
   202 	return KErrGeneral;
       
   203 	}
       
   204 
       
   205 TUint TACLLinkState::Write(CACLLink& /*aContext*/, const TDesC8& /*aData*/, TUint /*aOptions*/, TSockAddr* /*aAddr*/) const
       
   206 	{
       
   207 	LOG_FUNC
       
   208 	LOG(_L("CACLLink: Write in base state - Dropping data..."));
       
   209 	return 0;
       
   210 	}
       
   211 
       
   212 TBool TACLLinkState::IsIdle() const
       
   213 	{
       
   214 	LOG_FUNC
       
   215 	return EFalse;
       
   216 	}
       
   217 
       
   218 void TACLLinkState::Park(CACLLink& /*aContext*/) const
       
   219 	{
       
   220 	LOG_FUNC
       
   221 	// ignore
       
   222 	}
       
   223 
       
   224 void TACLLinkState::Unpark(CACLLink& /*aContext*/) const
       
   225 	{
       
   226 	LOG_FUNC
       
   227 	// ignore
       
   228 	}
       
   229 
       
   230 //----------------------------------------------------------------------------------
       
   231 
       
   232 TACLLinkStateListening::TACLLinkStateListening(CACLLinkStateFactory& aFactory)
       
   233 : TACLLinkState(aFactory)
       
   234 	{
       
   235 	LOG_FUNC
       
   236 	STATENAME("Listening");
       
   237 	}
       
   238 
       
   239 void TACLLinkStateListening::Enter(CACLLink& aContext) const
       
   240 	{
       
   241 	LOG_FUNC
       
   242 	TInt err = aContext.iLinksMan.AddListener(aContext, EACLLink);
       
   243 	if (err)
       
   244 		{
       
   245 		__ASSERT_DEBUG(err!=KErrInUse, PanicInState(EBTACLAlreadyBoundToPhysicalLink));
       
   246 		aContext.iSocket->Error(err, MSocketNotify::EErrorFatal);
       
   247 		ChangeState(aContext, CACLLinkStateFactory::EClosed);
       
   248 		}
       
   249 	}
       
   250 
       
   251 
       
   252 TBool TACLLinkStateListening::ConnectRequest(CACLLink& aContext,
       
   253 											 const TBTConnect& /*aConnectDetails*/,
       
   254 											 const CPhysicalLink& aPhysicalLink) const
       
   255 	{
       
   256 	LOG_FUNC										
       
   257 	// ah! we have a connection
       
   258 	/*	super - now BT1.1/1.2 says we don't need to do anything - 
       
   259 	ACL is here for free: with same handle as PhysicalLink.
       
   260 	We do however need to introduce ourselves to ACL Q
       
   261 	*/
       
   262 	LOG(_L("CACLLink: Physical Channel Up - Spawning..."));
       
   263 
       
   264 	// clone the sap - we only support *one* child at present since
       
   265 	// we dont expose ACL sockets to ESOCK - only to L2CAP who will 
       
   266 	// only attempt to Start one child at a time
       
   267 	TRAPD(err, SpawnL(aContext, const_cast<CPhysicalLink&>(aPhysicalLink)));
       
   268 
       
   269 	return (err==KErrNone);
       
   270 	}
       
   271 
       
   272 
       
   273 void TACLLinkStateListening::SpawnL(CACLLink& aContext, CPhysicalLink& aPhysicalLink) const
       
   274 /**
       
   275 	Called when a PassiveSAP wants to create a (connected) child of itself
       
   276 **/
       
   277 	{
       
   278 	LOG_FUNC
       
   279 	//Listening SAP only keeps one pointer to accepting SAP so we 
       
   280 	//can't have more than one outstanding accepting SAP
       
   281 	if(aContext.iChild)
       
   282 		{
       
   283 		LOG(_L("TACLLinkStateListening::SpawnL: there is already an outstanding accepting SAP, can't spawn now"));
       
   284 		User::Leave(KErrInUse);
       
   285 		}
       
   286 
       
   287 	CACLLink* child = CACLLink::NewLC(aContext.iLinksMan,
       
   288 									  &aPhysicalLink,
       
   289 									  aContext.iProtocol);
       
   290 	
       
   291 	User::LeaveIfError(child->BindLink(EACLLink, aPhysicalLink));
       
   292 	CleanupStack::Pop(child);
       
   293 
       
   294 	// tell child about parent
       
   295 	child->ListeningSAP() = &aContext;
       
   296 
       
   297 	// and parent about child
       
   298 	aContext.iChild = child;
       
   299 
       
   300 	// configure the SAP
       
   301 	child->iRemoteDev = aPhysicalLink.BDAddr();
       
   302 	child->iLocalPort = aContext.iLocalPort;
       
   303 
       
   304 	// transition for child is Closed->WaitForStart
       
   305 	ChangeState(*child, CACLLinkStateFactory::EAccepting);
       
   306 	}
       
   307 
       
   308 void TACLLinkStateListening::Shutdown(CACLLink& aContext, CServProviderBase::TCloseType aCloseType) const
       
   309 	{
       
   310 	LOG_FUNC
       
   311 	ChangeState(aContext, CACLLinkStateFactory::EClosed);
       
   312 
       
   313 	if(aContext.iChild)
       
   314 		{
       
   315 		//As soon as this method returns, this SAP could be deleted.
       
   316 		//Notify the child.
       
   317 		aContext.iChild->Shutdown(CServProviderBase::EImmediate);
       
   318 
       
   319 		//If the child was in EAccepting state, the shutdown will move it to EClosing. It
       
   320 		//will still be bound to PHY, and when the ConnectComplete arrives the PHY will
       
   321 		//still route it to the child. If the parent has been deleted by then, the child
       
   322 		//will cause a panic. The best thing to do is delete the child now.
       
   323 		//N.B. It is important to Shutdown the child before deleting it, because if it
       
   324 		//was in EAccepting state calling Shutdown stops its watchdog.
       
   325 		aContext.DeleteChild(aContext.iChild);
       
   326 		aContext.iChild=NULL; //Not sure if this is needed, but it'll do no harm.
       
   327 		}
       
   328 
       
   329 	if (aCloseType == CServProviderBase::ENormal)
       
   330 		{
       
   331 		aContext.Socket()->CanClose();
       
   332 		}
       
   333 	}
       
   334 
       
   335 void TACLLinkStateListening::Deletion(CACLLink& aContext) const
       
   336 	{
       
   337 	LOG_FUNC
       
   338 	delete aContext.iChild;
       
   339 	}
       
   340 
       
   341 void TACLLinkStateListening::Exit(CACLLink& aContext) const
       
   342 	{
       
   343 	LOG_FUNC
       
   344 	aContext.iLinksMan.RemoveListener(aContext);
       
   345 	}
       
   346 
       
   347 void TACLLinkStateListening::Error(CACLLink& /*aContext*/, TInt __DEBUG_ONLY(aError)) const
       
   348 	{
       
   349 	LOG_FUNC
       
   350 	// Don't propagate the error as listeners don't care if the hardware has gone down
       
   351 	__ASSERT_DEBUG(aError==KErrHardwareNotAvailable, PanicInState(EBTACLSAPUnexpectedEvent));
       
   352 	}
       
   353 
       
   354 //----------------------------------------------------------------------------------
       
   355 
       
   356 TACLLinkStateAccepting::TACLLinkStateAccepting(CACLLinkStateFactory& aFactory)
       
   357 : TACLLinkState(aFactory)
       
   358 	{
       
   359 	LOG_FUNC
       
   360 	STATENAME("Accepting");
       
   361 	}
       
   362 
       
   363 void TACLLinkStateAccepting::Enter(CACLLink& aContext) const
       
   364 	{
       
   365 	LOG_FUNC
       
   366 	// start watchdog
       
   367 	aContext.iAcceptWatchdog.Start();
       
   368 	// If the link is accepting then it must be being remotely initiated.
       
   369 	aContext.SetInitiationState(CACLLink::ERemotelyInitiated);
       
   370 	if(aContext.iLinksMan.IsAcceptPairedOnlyMode())
       
   371 		{
       
   372 		// Start an access request for appropriate security - this will start as
       
   373 		// the physical link is established.
       
   374 		aContext.StartAccessRequest(*(aContext.ListeningSAP()));
       
   375 		}
       
   376 	}
       
   377 
       
   378 void TACLLinkStateAccepting::Exit(CACLLink& aContext) const
       
   379  	{
       
   380 	LOG_FUNC
       
   381  	//Ensure watchdog has been cancelled (safe to call Cancel multiple times)
       
   382  	aContext.iAcceptWatchdog.Cancel();
       
   383  	}
       
   384 
       
   385 void TACLLinkStateAccepting::ConnectComplete(CACLLink& aContext, const TBTConnect& /*aConnect*/) const
       
   386 	{
       
   387 	LOG_FUNC
       
   388 	// cancel watchdog
       
   389 	aContext.iAcceptWatchdog.Cancel();
       
   390 
       
   391 	// must wait until started
       
   392 	ChangeState(aContext, CACLLinkStateFactory::EWaitForStart);
       
   393 	// let the listening Socket know...
       
   394 	__ASSERT_DEBUG(aContext.ListeningSAP()->Socket(), PanicInState(EBTACLSAPNullSocket));
       
   395 	aContext.ListeningSAP()->Socket()->ConnectComplete(aContext);	// tell listening socket about its new SAP
       
   396 	}
       
   397 
       
   398 void TACLLinkStateAccepting::Timeout(CACLLink& aContext, TBasebandTimeout aTimeout) const
       
   399 	{
       
   400 	LOG_FUNC
       
   401 	if (aTimeout == EAccept)
       
   402 		{
       
   403 		// the accept never worked - give up
       
   404 		Error(aContext, KErrTimedOut);
       
   405 		}
       
   406 	}
       
   407 
       
   408 void TACLLinkStateAccepting::Deletion(CACLLink& aContext) const
       
   409 	{
       
   410 	LOG_FUNC
       
   411 	aContext.ListeningSAP()->RemoveChild(&aContext);
       
   412 	}
       
   413 
       
   414 void TACLLinkStateAccepting::Disconnection(CACLLink& aContext) const
       
   415 	{
       
   416 	LOG_FUNC
       
   417 	// This will be called if there is a hardware error - give up
       
   418 	Error(aContext, KErrDisconnected);
       
   419 	}
       
   420 
       
   421 void TACLLinkStateAccepting::Error(CACLLink& aContext, TInt /*aError*/) const
       
   422 	{
       
   423 	LOG_FUNC
       
   424 	// unbind from physical link
       
   425 	aContext.UnbindLink(EACLLink);
       
   426 	// cancel watchdog
       
   427 	aContext.iAcceptWatchdog.Cancel();
       
   428 	aContext.ListeningSAP()->DeleteChild(&aContext);
       
   429 	}
       
   430 
       
   431 void TACLLinkStateAccepting::Shutdown(CACLLink& aContext, CServProviderBase::TCloseType /*aCloseType*/) const
       
   432 	{
       
   433 	LOG_FUNC
       
   434 	// we're not wanted - close
       
   435 	ChangeState(aContext, CACLLinkStateFactory::EClosing);
       
   436 	}
       
   437 
       
   438 //----------------------------------------------------------------------------------
       
   439 
       
   440 
       
   441 TACLLinkStateWaitForStart::TACLLinkStateWaitForStart(CACLLinkStateFactory& aFactory)
       
   442 : TACLLinkState(aFactory)
       
   443 	{
       
   444 	LOG_FUNC
       
   445 	STATENAME("WaitForStart");
       
   446 	}
       
   447 
       
   448 void TACLLinkStateWaitForStart::Enter(CACLLink& __DEBUG_ONLY(aContext)) const
       
   449 	{
       
   450 	LOG_FUNC
       
   451 	__ASSERT_DEBUG(aContext.ListeningSAP(), PanicInState(EBTACLSAPParentlessChild));
       
   452 	}
       
   453 
       
   454 void TACLLinkStateWaitForStart::Start(CACLLink& aContext) const
       
   455 	{
       
   456 	LOG_FUNC
       
   457 	// transfer ownership to higher entity
       
   458 	aContext.ListeningSAP()->RemoveChild(&aContext);
       
   459 	aContext.ListeningSAP() = NULL;
       
   460 	TInt err = aContext.OpenLogicalLink();
       
   461 	if (err == KErrNone)
       
   462 		{
       
   463 		ChangeState(aContext, CACLLinkStateFactory::EOpen);
       
   464 		}
       
   465 	else
       
   466 		{
       
   467 		Error(aContext, err);
       
   468 		}
       
   469 	}
       
   470 
       
   471 void TACLLinkStateWaitForStart::Deletion(CACLLink& aContext) const
       
   472 	{
       
   473 	LOG_FUNC
       
   474 	aContext.ListeningSAP()->RemoveChild(&aContext);
       
   475 	}
       
   476 
       
   477 void TACLLinkStateWaitForStart::Error(CACLLink& aContext, TInt /*aError*/) const
       
   478 	{
       
   479 	LOG_FUNC
       
   480 	ChangeState(aContext, CACLLinkStateFactory::EWaitForStartError);
       
   481 	}
       
   482 
       
   483 void TACLLinkStateWaitForStart::Park(CACLLink& aContext) const
       
   484 	{
       
   485 	LOG_FUNC
       
   486 	// blimey! already gone into park - dont tell socket anything
       
   487 	ChangeState(aContext, CACLLinkStateFactory::EWaitForStartParked);	
       
   488 	}
       
   489 
       
   490 void TACLLinkStateWaitForStart::Disconnection(CACLLink& aContext) const
       
   491 	{
       
   492 	LOG_FUNC
       
   493 	aContext.ListeningSAP()->DeleteChild(&aContext);
       
   494 	}
       
   495 
       
   496 void TACLLinkStateWaitForStart::Shutdown(CACLLink& aContext, CServProviderBase::TCloseType /*aCloseType*/) const
       
   497 	{
       
   498 	LOG_FUNC
       
   499 	// just go
       
   500 	ChangeState(aContext, CACLLinkStateFactory::EClosing);
       
   501 	}
       
   502 
       
   503 //----------------------------------------------------------------------------------
       
   504 
       
   505 TACLLinkStateWaitForStartError::TACLLinkStateWaitForStartError(CACLLinkStateFactory& aFactory)
       
   506 : TACLLinkState(aFactory)
       
   507 	{
       
   508 	LOG_FUNC
       
   509 	STATENAME("Error");
       
   510 	}
       
   511 
       
   512 void TACLLinkStateWaitForStartError::Start(CACLLink& aContext) const
       
   513 	{
       
   514 	LOG_FUNC
       
   515 	// summat went wrong - close and remove this acceptor
       
   516 	ChangeState(aContext, CACLLinkStateFactory::EClosed);
       
   517 	aContext.Socket()->Disconnect();
       
   518 
       
   519 	aContext.ListeningSAP()->RemoveChild(&aContext);
       
   520 	}
       
   521 
       
   522 void TACLLinkStateWaitForStartError::Disconnection(CACLLink& /*aContext*/) const
       
   523 	{
       
   524 	LOG_FUNC
       
   525 	//Release build should silently ignore the event
       
   526 	__ASSERT_DEBUG(EFalse,PanicInState(EBTACLSAPUnexpectedEvent));	
       
   527 	}
       
   528 
       
   529 void TACLLinkStateWaitForStartError::Error(CACLLink& /*aContext*/, TInt /*aError*/) const
       
   530 	{
       
   531 	LOG_FUNC
       
   532 	//Release build should silently ignore the event
       
   533 	__ASSERT_DEBUG(EFalse,PanicInState(EBTACLSAPUnexpectedEvent));
       
   534 	}	
       
   535 	
       
   536 void TACLLinkStateWaitForStartError::Deletion(CACLLink& aContext) const
       
   537 /*
       
   538 In WaitForStartError state we expect ESock to send a Start. But deletion could occur
       
   539 if ESock deletes the parent SAP.
       
   540 */
       
   541 	{
       
   542 	LOG_FUNC
       
   543 	aContext.ListeningSAP()->RemoveChild(&aContext);
       
   544 	}
       
   545 	
       
   546 //----------------------------------------------------------------------------------
       
   547 
       
   548 TACLLinkStateWaitForStartParked::TACLLinkStateWaitForStartParked(CACLLinkStateFactory& aFactory)
       
   549 : TACLLinkStateWaitForStart(aFactory)
       
   550 	{
       
   551 	LOG_FUNC
       
   552 	STATENAME("WaitForStartParked");
       
   553 	}
       
   554 
       
   555 void TACLLinkStateWaitForStartParked::Start(CACLLink& aContext) const
       
   556 	{
       
   557 	LOG_FUNC
       
   558 	// transfer ownership to higher entity
       
   559 	aContext.ListeningSAP()->RemoveChild(&aContext);
       
   560 	aContext.ListeningSAP() = NULL;
       
   561 	ChangeState(aContext, CACLLinkStateFactory::EOpenParked);
       
   562 	}
       
   563 
       
   564 void TACLLinkStateWaitForStartParked::Unpark(CACLLink& aContext) const
       
   565 	{
       
   566 	LOG_FUNC
       
   567 	// that's nice - un-parked!
       
   568 	ChangeState(aContext, CACLLinkStateFactory::EWaitForStart);
       
   569 	}
       
   570 
       
   571 //----------------------------------------------------------------------------------
       
   572 
       
   573 TACLLinkStateWaitForLink::TACLLinkStateWaitForLink(CACLLinkStateFactory& aFactory)
       
   574 : TACLLinkState(aFactory)
       
   575 	{
       
   576 	LOG_FUNC
       
   577 	STATENAME("WaitForLink");
       
   578 	}
       
   579 
       
   580 void TACLLinkStateWaitForLink::ConnectComplete(CACLLink& aContext, const TBTConnect& aConnectDetails) const
       
   581 	{
       
   582 	LOG_FUNC
       
   583 	/*	super - now BT1.1/1.2 says we don't need to do anything - 
       
   584 	ACL is here for free: with same handle as PhysicalLink.
       
   585 	We do however need to introduce ourselves to ACL Q
       
   586 	*/
       
   587 	LOG(_L("CACLLink: Physical Channel Up"))
       
   588 	__ASSERT_DEBUG(aConnectDetails.iBdaddr == aContext.iPhysicalLink->BDAddr(), PanicInState(EBTACLSAPWrongPhysicalLink));
       
   589 	aContext.iRemoteDev = aConnectDetails.iBdaddr;
       
   590 	TInt err = aContext.OpenLogicalLink();
       
   591 	if (err == KErrNone)
       
   592 		{
       
   593 		ChangeState(aContext, CACLLinkStateFactory::EOpen);
       
   594 		aContext.Socket()->ConnectComplete();
       
   595 		}
       
   596 	else
       
   597 		{
       
   598 		Error(aContext, err);
       
   599 		}
       
   600 	}
       
   601 
       
   602 void TACLLinkStateWaitForLink::Error(CACLLink& aContext, TInt aError) const
       
   603 	{
       
   604 	LOG_FUNC
       
   605 	ChangeState(aContext, CACLLinkStateFactory::EClosed);
       
   606 	aContext.Socket()->Error(aError, MSocketNotify::EErrorConnect);
       
   607 	}
       
   608 
       
   609 void TACLLinkStateWaitForLink::Exit(CACLLink& /*aContext*/) const
       
   610 	{
       
   611 	LOG_FUNC
       
   612 	}
       
   613 
       
   614 void TACLLinkStateWaitForLink::Shutdown(CACLLink& aContext, CServProviderBase::TCloseType /*aCloseType*/) const
       
   615 	{
       
   616 	LOG_FUNC
       
   617 	// just change to closing - we'll get notified of PhyUp, but that'll get swallowed
       
   618 	// and the connection will timeout and die.
       
   619 	ChangeState(aContext, CACLLinkStateFactory::EClosing);
       
   620 	}
       
   621 
       
   622 void TACLLinkStateWaitForLink::Disconnection(CACLLink& aContext) const
       
   623 	{
       
   624 	LOG_FUNC
       
   625 	//Physical link is down
       
   626 	Error(aContext, KErrCouldNotConnect);
       
   627 	}
       
   628 	
       
   629 //----------------------------------------------------------------------------------
       
   630 
       
   631 TACLLinkStateOpen::TACLLinkStateOpen(CACLLinkStateFactory& aFactory)
       
   632 : TACLLinkState(aFactory)
       
   633 	{
       
   634 	LOG_FUNC
       
   635 	STATENAME("Open");
       
   636 	}
       
   637 
       
   638 void TACLLinkStateOpen::Enter(CACLLink& /*aContext*/) const
       
   639 	{
       
   640 	LOG_FUNC
       
   641 	}
       
   642 
       
   643 void TACLLinkStateOpen::Disconnection(CACLLink& aContext) const
       
   644 	{
       
   645 	LOG_FUNC
       
   646 	// an unexpected phy loss
       
   647 	LOG(_L("CACLLink: Physical Channel Down"))
       
   648 
       
   649 	// No more data will appear so close
       
   650 	aContext.CloseLogicalLink();
       
   651 	ChangeState(aContext, CACLLinkStateFactory::EClosed);
       
   652 	aContext.Socket()->Disconnect();
       
   653 	}
       
   654 	
       
   655 void TACLLinkStateOpen::Error(CACLLink& aContext, TInt aError) const
       
   656 	{
       
   657 	LOG_FUNC
       
   658 	// eg for weird times when we get another (PHY) connect complete with error!
       
   659 	ChangeState(aContext, CACLLinkStateFactory::EClosed);
       
   660 	aContext.Socket()->Error(aError, MSocketNotify::EErrorAllOperations);
       
   661 	}
       
   662 
       
   663 TUint TACLLinkStateOpen::Write(CACLLink& aContext, const TDesC8& aData, TUint aOptions, TSockAddr* aAddr) const
       
   664 	{
       
   665 	LOG_FUNC
       
   666 	// Note: This method returns the number of data
       
   667 	// fragments written (normally 1), NOT the number of bytes.
       
   668 	LOG(_L("TACLLinkStateOpen::Write"));
       
   669 
       
   670 	// we only allow 8 bit flags
       
   671 	__ASSERT_DEBUG(aOptions < KMaxTUint8, PanicInState(EBTACLSAPBadFlagsOnWrite));
       
   672 
       
   673 	TUint8 flags = static_cast<TUint8>(aOptions);
       
   674 
       
   675 	// check not trying to do piconet broadcast - active bc is OK
       
   676 	__ASSERT_DEBUG(!((flags >> KPacketPBBCFlagShift) & KPacketBCFlagMask),
       
   677 		PanicInState(EBTACLSAPDoesNotSupportPiconetBroadcast));
       
   678 
       
   679 	// check that L2CAP isn't trying to broadcast
       
   680 	__ASSERT_DEBUG(!(((flags >> KPacketPBBCFlagShift) & KPacketBCFlagMask)
       
   681 		&& aContext.iLocalPort==EACLPortL2CAP), PanicInState(EBTACLSAPDoesNotSupportBroadcastL2CAP));
       
   682 
       
   683 
       
   684 	CACLDataQController& aclQctrl = aContext.iProtocol.ACLController();
       
   685 	CACLDataItem* dataItem = aclQctrl.GetFreeItem(); // we don't own it - but might be NULL
       
   686 
       
   687 	TUint retVal;
       
   688 
       
   689 	if (!dataItem)
       
   690 		{
       
   691 		// no space on pool
       
   692 		LOG(_L("\tno space in ACL data pool- blocking socket"))
       
   693 		aContext.iSocketBlocked = ETrue;
       
   694 		retVal = 0; // could not write anything - notify later
       
   695 		}
       
   696 	else
       
   697 		{
       
   698 		// space on pool...so format get the HCIFacade to format and queue the frame
       
   699 		dataItem->SetElementHandle(aAddr);
       
   700 		retVal = aContext.DoWrite(*dataItem, aclQctrl, aData, flags);
       
   701 		}
       
   702 
       
   703 	LOG1(_L("TACLLinkStateOpen::Write retVal = %d"), retVal);
       
   704 	return retVal;
       
   705 	}
       
   706 
       
   707 
       
   708 void TACLLinkStateOpen::DataReceived(CACLLink& aContext, TUint8 aFlag, const TDesC8& aData) const
       
   709 	{
       
   710 	LOG_FUNC
       
   711 	aContext.NotifyDataToSocket(aFlag, aData);
       
   712 	}
       
   713 
       
   714 void TACLLinkStateOpen::Park(CACLLink& aContext) const
       
   715 	{
       
   716 	LOG_FUNC
       
   717 	ChangeState(aContext, CACLLinkStateFactory::EOpenParked);
       
   718 	}
       
   719 
       
   720 void TACLLinkStateOpen::Shutdown(CACLLink& aContext, CServProviderBase::TCloseType /*aCloseType*/) const
       
   721 	{
       
   722 	LOG_FUNC
       
   723 	// an ACL link cannot be closed with the underlying PHY going.
       
   724 	// to congrue with the spec we keep this object all the time the PHY
       
   725 	// is around.
       
   726 //	__ASSERT_DEBUG(aCloseType == CServProviderBase::ENormal, PanicInState(EBTACLSAPNotSupportedFeature));
       
   727 
       
   728 	// Change state first in case the ACL is currently in Park mode.
       
   729 	// This will allow the logic in the Exit of the Open Park state
       
   730 	// to un-park the link before it is disconnected.
       
   731 	ChangeState(aContext, CACLLinkStateFactory::EClosing); // we close when the PHY says
       
   732 	}
       
   733 
       
   734 
       
   735 void TACLLinkStateOpen::Exit(CACLLink& /*aContext*/) const
       
   736 	{
       
   737 	LOG_FUNC
       
   738 	}
       
   739 
       
   740 //----------------------------------------------------------------------------------
       
   741 
       
   742 TACLLinkStateOpenParked::TACLLinkStateOpenParked(CACLLinkStateFactory& aFactory)
       
   743 : TACLLinkStateOpen(aFactory)
       
   744 	{
       
   745 	LOG_FUNC
       
   746 	STATENAME("OpenParked");
       
   747 	}
       
   748 
       
   749 void TACLLinkStateOpenParked::Enter(CACLLink& aContext) const
       
   750 	{
       
   751 	LOG_FUNC
       
   752 	// signal ACL Data Q controller that we've parked up
       
   753 	aContext.ParkLogicalLink();
       
   754 	}
       
   755 
       
   756 TUint TACLLinkStateOpenParked::Write(CACLLink& /*aContext*/, const TDesC8& /*aData*/, TUint /*aOptions*/, TSockAddr* /*aAddr*/) const
       
   757 	{
       
   758 	LOG_FUNC
       
   759 	// can't - parked; and don't support piconet broadcast yet...
       
   760 	// for active broadcast support that in open state
       
   761 	return 0;
       
   762 	}
       
   763 
       
   764 void TACLLinkStateOpenParked::Unpark(CACLLink& aContext) const
       
   765 	{
       
   766 	LOG_FUNC
       
   767 	ChangeState(aContext, CACLLinkStateFactory::EOpen);
       
   768 
       
   769 	// flow control on socket
       
   770 	aContext.Socket()->CanSend();
       
   771 	}
       
   772 
       
   773 void TACLLinkStateOpenParked::DataReceived(CACLLink& aContext, TUint8 aFlag, const TDesC8& aData) const
       
   774 	{
       
   775 	LOG_FUNC
       
   776 	// We handle data in this state to allow for the race condition between
       
   777 	// the Mode Change [Park] event and data that was received at the HC just
       
   778 	// prior to Park mode being entered.
       
   779 	aContext.NotifyDataToSocket(aFlag, aData);
       
   780 	}
       
   781 
       
   782 void TACLLinkStateOpenParked::Exit(CACLLink& aContext) const
       
   783 	{
       
   784 	LOG_FUNC
       
   785 	// signal ACL Data Q controller that we're un-parking
       
   786 	aContext.UnparkLogicalLink();
       
   787 	}
       
   788 
       
   789 //----------------------------------------------------------------------------------
       
   790 
       
   791 TACLLinkStateClosing::TACLLinkStateClosing(CACLLinkStateFactory& aFactory)
       
   792 : TACLLinkState(aFactory)
       
   793 	{
       
   794 	LOG_FUNC
       
   795 	STATENAME("Closing");
       
   796 	}
       
   797 
       
   798 void TACLLinkStateClosing::ActiveOpen(CACLLink& aContext) const
       
   799 	{
       
   800 	LOG_FUNC
       
   801 	// erk - have been asked to Open as we're closing down
       
   802 	// the link hasn't gone yet, so just say it's there!
       
   803 	
       
   804 	// Set as locally initiated (even if previously it was remotely initiated)
       
   805 	aContext.SetInitiationState(CACLLink::ELocallyInitiated);
       
   806 	ChangeState(aContext, CACLLinkStateFactory::EOpen);
       
   807 	aContext.Socket()->ConnectComplete();
       
   808 	}
       
   809 
       
   810 void TACLLinkStateClosing::Shutdown(CACLLink& /*aContext*/, CServProviderBase::TCloseType /*aCloseType*/) const
       
   811 	{
       
   812 	LOG_FUNC
       
   813 	// we are!  just ignore and continue
       
   814 	}
       
   815 
       
   816 void TACLLinkStateClosing::Disconnection(CACLLink& aContext) const
       
   817 	{
       
   818 	LOG_FUNC
       
   819 	// an expected phy down!
       
   820 
       
   821 	// No more data will appear, so close
       
   822 	aContext.CloseLogicalLink();
       
   823 
       
   824 	ChangeState(aContext, CACLLinkStateFactory::EClosed);
       
   825 	aContext.Socket()->CanClose();
       
   826 	}
       
   827 
       
   828 void TACLLinkStateClosing::Enter(CACLLink& aContext) const
       
   829 	{
       
   830 	LOG_FUNC
       
   831 	// Inform the physical link that this link has become idle.
       
   832 	aContext.LinkStateIdle();
       
   833 	}
       
   834 
       
   835 void TACLLinkStateClosing::Deletion(CACLLink& /*aContext*/) const
       
   836 	{
       
   837 	LOG_FUNC
       
   838 	// allowed
       
   839 	}
       
   840 
       
   841 TBool TACLLinkStateClosing::IsIdle() const
       
   842 	{
       
   843 	LOG_FUNC
       
   844 	return ETrue;
       
   845 	}
       
   846 
       
   847 void TACLLinkStateClosing::DataReceived(CACLLink& aContext, TUint8 aFlag, const TDesC8& aData) const
       
   848 	{
       
   849 	LOG_FUNC
       
   850 	// got data for socket - that's fine: deliver it to decide
       
   851 	aContext.NotifyDataToSocket(aFlag, aData);
       
   852 	}
       
   853 	
       
   854 TUint TACLLinkStateClosing::Write(CACLLink& /*aContext*/, const TDesC8& /*aData*/, TUint /*aOptions*/, TSockAddr* /*aAddr*/) const
       
   855 	{
       
   856 	LOG_FUNC
       
   857 	//Drop, we are not interested in data anymore.
       
   858 	return 0;
       
   859 	}
       
   860 
       
   861 void TACLLinkStateClosing::Error(CACLLink& aContext, TInt /*aError*/) const
       
   862 	{
       
   863 	LOG_FUNC
       
   864 	// This method is reached by receiving a Disconnection Complete Event with Status field != EOk,
       
   865 	// in this case we don't want to error the socket - so instead it is just closed
       
   866 	ChangeState(aContext, CACLLinkStateFactory::EClosed);
       
   867 	aContext.Socket()->CanClose();
       
   868 	}
       
   869 
       
   870 //----------------------------------------------------------------------------------
       
   871 
       
   872 TACLLinkStateClosed::TACLLinkStateClosed(CACLLinkStateFactory& aFactory)
       
   873 : TACLLinkState(aFactory)
       
   874 	{
       
   875 	LOG_FUNC
       
   876 	STATENAME("Closed");
       
   877 	}
       
   878 
       
   879 void TACLLinkStateClosed::Enter(CACLLink& aContext) const
       
   880 	{
       
   881 	LOG_FUNC
       
   882 	aContext.ClearInitiationState(); // once closed, there is no direction
       
   883 	aContext.ClearPhysicalLink();
       
   884 	}
       
   885 
       
   886 void TACLLinkStateClosed::Start(CACLLink& /*aContext*/) const
       
   887 	{
       
   888 	LOG_FUNC
       
   889 	// gulp this - don't need to transition
       
   890 	}
       
   891 
       
   892 void TACLLinkStateClosed::Shutdown(CACLLink& aContext, CServProviderBase::TCloseType aCloseType) const
       
   893 	{
       
   894 	LOG_FUNC
       
   895 	if (aCloseType != CServProviderBase::EImmediate)
       
   896 		{
       
   897 		aContext.Socket()->CanClose();
       
   898 		}
       
   899 	}
       
   900 
       
   901 void TACLLinkStateClosed::ActiveOpen(CACLLink& aContext) const
       
   902 	{
       
   903 	LOG_FUNC
       
   904 	// create ACL link
       
   905 	ChangeState(aContext, CACLLinkStateFactory::EWaitForLink);
       
   906 	TRAPD(err, aContext.BindAndConnectPhysicalLinkL());
       
   907 
       
   908 	if (err != KErrNone)
       
   909 		{
       
   910 		aContext.Error(err);
       
   911 		}
       
   912 	else
       
   913 		{
       
   914 		// Successful active open means that we've been locally initiated.
       
   915 		aContext.SetInitiationState(CACLLink::ELocallyInitiated);
       
   916 		}
       
   917 	}
       
   918 
       
   919 TInt TACLLinkStateClosed::PassiveOpen(CACLLink& aContext, TUint __DEBUG_ONLY(aQueSize)) const
       
   920 	{
       
   921 	LOG_FUNC
       
   922 	__ASSERT_DEBUG(aQueSize == 1, PanicInState(EBTACLSAPUnsupportedQueSize));
       
   923 	// only support a QueSize of 1 - we don't expose the ACL Links to ESOCK
       
   924 	// for use by RSockets; furhter we enforce L2CAP to *start* us synchronously
       
   925 	// upon ACL link up
       
   926 
       
   927 	ChangeState(aContext, CACLLinkStateFactory::EListening);
       
   928 
       
   929 	return KErrNone;
       
   930 	}
       
   931 
       
   932 void TACLLinkStateClosed::Deletion(CACLLink& /*aContext*/) const
       
   933 	{
       
   934 	LOG_FUNC
       
   935 	// allowed deletion
       
   936 	}
       
   937 
       
   938 TBool TACLLinkStateClosed::IsIdle() const
       
   939 	{
       
   940 	LOG_FUNC
       
   941 	return ETrue;
       
   942 	}
       
   943 
       
   944 //----------------------------------------------------------------------------------
       
   945 
       
   946 CACLLink* CACLLink::NewLC(CPhysicalLinksManager& aLinksMan, CPhysicalLink* aConnection, CLinkMgrProtocol& aProtocol)
       
   947 	{
       
   948 	LOG_STATIC_FUNC
       
   949 	CACLLink* s = new(ELeave) CACLLink(aLinksMan, aConnection, aProtocol);
       
   950 	CleanupStack::PushL(s);
       
   951 	s->ConstructL();
       
   952 	return s;
       
   953 	}
       
   954 
       
   955 
       
   956 CACLLink* CACLLink::NewL(CPhysicalLinksManager& aLinksMan, CPhysicalLink* aConnection, CLinkMgrProtocol& aProtocol)
       
   957 	{
       
   958 	LOG_STATIC_FUNC
       
   959 	CACLLink* s = NewLC(aLinksMan, aConnection, aProtocol);
       
   960 	CleanupStack::Pop(s);
       
   961 	return s;
       
   962 	}
       
   963 
       
   964 
       
   965 CACLLink::CACLLink(CPhysicalLinksManager& aManager,
       
   966 				   CPhysicalLink* aConnection,
       
   967 				   CLinkMgrProtocol& aProtocol)
       
   968 : 	CBTBasebandSAP(aManager, aConnection),
       
   969 	iProtocol(aProtocol),
       
   970 	iSocketBlocked(EFalse)
       
   971 	{
       
   972 	LOG_FUNC
       
   973 	iState = &iProtocol.ACLStateFactory().GetState(CACLLinkStateFactory::EClosed);
       
   974 
       
   975 	// Hard-coded security for ACL level security (not service level).
       
   976 	// MITM desired is applied to ensure authentication takes place (if
       
   977 	// since authentication is normally eq. MITM protection).  Pairing
       
   978 	// is prevented where appropriate.
       
   979 	// (See Paired Only Connections Mode for why this is used).
       
   980 	iSecurity.SetAuthentication(EMitmDesired);
       
   981 	iSecurity.SetEncryption(EFalse);
       
   982 	iSecurity.SetAuthorisation(EFalse);
       
   983 	}
       
   984 
       
   985 CACLLink::~CACLLink()
       
   986 	{
       
   987 	LOG_FUNC
       
   988 	// CloseLogicalLink() should have been called by now, but just in case...
       
   989 	if ( iHandle != KInvalidConnectionHandle )
       
   990 		{
       
   991 		CloseLogicalLink();
       
   992 		}
       
   993 	
       
   994 	// There could be an access request outstanding
       
   995 	CancelAccessRequest();
       
   996 	
       
   997 	iState->Deletion(*this);
       
   998 	
       
   999 	UnbindLink(EACLLink);
       
  1000 
       
  1001 	__ASSERT_DEBUG(!iChild, Panic(EAclSapChildStillPresentAtDestruction));
       
  1002 	}
       
  1003 
       
  1004 void CACLLink::ConstructL()
       
  1005 	{
       
  1006 	LOG_FUNC
       
  1007 	CBTBasebandSAP::ConstructL();
       
  1008 	}
       
  1009 
       
  1010 void CACLLink::ActiveOpen()
       
  1011 	{
       
  1012 	LOG_FUNC
       
  1013 	iState->ActiveOpen(*this);
       
  1014 	}
       
  1015 
       
  1016 void CACLLink::BindAndConnectPhysicalLinkL()
       
  1017 	{
       
  1018 	LOG_FUNC
       
  1019 	if(!(Baseband().IsACLPossible()))
       
  1020 		{
       
  1021 		User::Leave(KErrInsufficientBasebandResources);
       
  1022 		}
       
  1023 
       
  1024 	iPhysicalLink = iLinksMan.FindPhysicalLink(iRemoteDev);
       
  1025 
       
  1026 	if (iPhysicalLink)
       
  1027 		{
       
  1028 		TBTBasebandLinkState::TLinkState linkState =  iPhysicalLink->LinkState().LinkState();
       
  1029 		if (linkState == TBTBasebandLinkState::ELinkDown)
       
  1030 			{
       
  1031 			// Incoming pending physical link connection. We must error here as we cannot 
       
  1032 			// know if the incoming connection will be successful or not.
       
  1033 			iPhysicalLink = NULL;
       
  1034 			User::Leave(KErrPendingPhysicalLink);
       
  1035 			}
       
  1036 
       
  1037 		User::LeaveIfError(BindLink(EACLLink, *iPhysicalLink));
       
  1038 
       
  1039 		if (linkState == TBTBasebandLinkState::ELinkUp)
       
  1040 			{
       
  1041 			// We have an existing, connected, physical link so we can complete this request
       
  1042 			TBTConnect connect;
       
  1043 			connect.iBdaddr = iPhysicalLink->BDAddr();
       
  1044 			ConnectComplete(connect);
       
  1045 			return;
       
  1046 			}
       
  1047 			
       
  1048 		// If we get here then we must have a pending active physical link connection. 
       
  1049 		// As we bind to it above then this connection request we be completed when
       
  1050 		// the physical link is completed.
       
  1051 		__ASSERT_ALWAYS(linkState == TBTBasebandLinkState::ELinkPending, Panic(EBTBasebandInvalidLinkState));
       
  1052 		}
       
  1053 	else
       
  1054 		{
       
  1055 		// New physical link connection request
       
  1056 		CPhysicalLink* physicalLink = &iLinksMan.NewPhysicalLinkL(iRemoteDev);
       
  1057 		// physicalLink is owned by the physical links manager.
       
  1058 		User::LeaveIfError(BindLink(EACLLink, *physicalLink));
       
  1059 		TInt err = iPhysicalLink->Connect();
       
  1060 		if(err != KErrNone)
       
  1061 			{
       
  1062 			// If we failed to connect then we should roll back the attachment
       
  1063 			ClearPhysicalLink();
       
  1064 			User::Leave(err);
       
  1065 			}
       
  1066 		}
       
  1067 	}
       
  1068 
       
  1069 TInt CACLLink::SetLocalName(TSockAddr& aAddr)
       
  1070 	{
       
  1071 	LOG_FUNC
       
  1072 	// Copy this address into iLocal*
       
  1073 	// Overwrite their BTAddr if it's wrong
       
  1074 	// Must check that the endpoint required is free
       
  1075 	TACLSockAddr aclAddr = TACLSockAddr::Cast(aAddr);
       
  1076 	TACLPort port = aclAddr.Port();
       
  1077 
       
  1078 	iLocalPort=port;
       
  1079 	return KErrNone;
       
  1080 	}
       
  1081 
       
  1082 TInt CACLLink::SetRemName(TSockAddr& aAddr)
       
  1083 	{
       
  1084 	LOG_FUNC
       
  1085 	// Copy this over
       
  1086 	__ASSERT_DEBUG(!ListeningSAP(), Panic(EBTACLSAPListenerSettingName)); // not applicable to listeners
       
  1087 
       
  1088 	TACLSockAddr bbAddr(aAddr);	// convert
       
  1089 	iRemoteDev = bbAddr.BTAddr();
       
  1090 	
       
  1091 	//try to get the details about the intended remote now
       
  1092 	return KErrNone;
       
  1093 	}
       
  1094 	
       
  1095 TInt CACLLink::PassiveOpen(TUint aQueSize)
       
  1096 	{
       
  1097 	LOG_FUNC
       
  1098 	return iState->PassiveOpen(*this, aQueSize);
       
  1099 	}
       
  1100 
       
  1101 
       
  1102 TInt CACLLink::GetOption(TUint aLevel,TUint aName,TDes8& aOption) const
       
  1103 	{
       
  1104 	LOG_FUNC
       
  1105 	TInt ret = KErrNone;
       
  1106 
       
  1107 	if (aLevel != KSolBtLM && aLevel != KSolBtACL)
       
  1108 		ret = KErrNotSupported;
       
  1109 	else
       
  1110 		{
       
  1111 		if (aLevel == KSolBtACL)
       
  1112 			{
       
  1113 			ret = DoACLGetOption(aName, aOption);
       
  1114 			}
       
  1115 		else
       
  1116 			{
       
  1117 			if (iPhysicalLink)
       
  1118 				{
       
  1119 				// forward to PHY
       
  1120 				ret = iPhysicalLink->GetOption(aLevel, aName, aOption);
       
  1121 				}
       
  1122 			else
       
  1123 				{
       
  1124 				// ho-hum!
       
  1125 				ret = KErrNotReady;
       
  1126 				}
       
  1127 			}
       
  1128 		}
       
  1129 	return ret;
       
  1130 	}
       
  1131 
       
  1132 
       
  1133 TInt CACLLink::DoACLGetOption(TUint aName,TDes8& aOption) const
       
  1134 	{
       
  1135 	LOG_FUNC
       
  1136 	TInt ret = KErrNone;
       
  1137 
       
  1138 	switch (aName)
       
  1139 		{
       
  1140 		case ELMOutboundACLSize:
       
  1141 			{
       
  1142 			if (aOption.Length() != sizeof(TInt))
       
  1143 				{
       
  1144 				ret = KErrArgument;
       
  1145 				}
       
  1146 			TInt val = iProtocol.ACLPacketMTU();
       
  1147 			aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
  1148 			break;
       
  1149 			}
       
  1150 		case ELMInboundACLSize:
       
  1151 			{
       
  1152 			if (aOption.Length() != sizeof(TInt))
       
  1153 				{
       
  1154 				ret = KErrArgument;
       
  1155 				}
       
  1156 			TInt val = KLinkMgrIncomingBufferSize;	// for now...
       
  1157 			aOption = TPtrC8(reinterpret_cast<TUint8*>(&val), sizeof(TInt));
       
  1158 			break;
       
  1159 			}
       
  1160 		case KLMGetACLHandle:
       
  1161 			{
       
  1162 			if (aOption.Length() != sizeof(THCIConnHandle))
       
  1163 				{
       
  1164 				ret = KErrArgument;
       
  1165 				}
       
  1166 			aOption = TPtrC8(reinterpret_cast<const TUint8*>(&iHandle), sizeof(THCIConnHandle));
       
  1167 			break;
       
  1168 			}
       
  1169 		default:
       
  1170 			__DEBUGGER();
       
  1171 			ret = KErrNotSupported;
       
  1172 		}
       
  1173 	return ret;
       
  1174 	}
       
  1175 
       
  1176 
       
  1177 TUint CACLLink::DoWrite(CACLDataItem& aItem, CACLDataQController& aQctrl,
       
  1178 					   const TDesC8& aData, TUint8 aOptions)
       
  1179 /**
       
  1180 	aFrame has been obtained by someone else (the state)
       
  1181 	- we can go and complete the write
       
  1182 **/
       
  1183 	{
       
  1184 	LOG_FUNC
       
  1185 	LOG1(_L("CACLLink::DoWrite aItem = 0x%08x"), &aItem);
       
  1186 
       
  1187 	__ASSERT_ALWAYS(aItem.Frame() != NULL, Panic(EBTACLSAPWriteDataItemWithNullFrame));
       
  1188 
       
  1189 	// Fill the item with data...
       
  1190 	iLinksMan.HCIFacade().FormatACLData(*aItem.Frame(), Handle(), aOptions, aData);
       
  1191 	//.. and add it to the pool
       
  1192 	aQctrl.AddItem(aItem);
       
  1193 	TInt ret = 1; //one data 'item'
       
  1194 	
       
  1195 	LOG1(_L("CACLLink::DoWrite ret = %d"), ret);
       
  1196 	return ret;
       
  1197 	}
       
  1198 
       
  1199 void CACLLink::Ioctl(TUint /*aLevel*/,TUint /*aName*/,TDes8* /*aOption*/)
       
  1200 	{
       
  1201 	LOG_FUNC
       
  1202 	// good stuff here!
       
  1203 	}
       
  1204 
       
  1205 void CACLLink::CancelIoctl(TUint /*aLevel*/,TUint /*aName*/)
       
  1206 	{
       
  1207 	LOG_FUNC
       
  1208 	// good stuff here!
       
  1209 	}
       
  1210 
       
  1211 TInt CACLLink::SAPSetOption(TUint aLevel,TUint aName,const TDesC8& aOption)
       
  1212 	{
       
  1213 	LOG_FUNC
       
  1214 	TInt rerr = KErrNone;
       
  1215 
       
  1216 	switch(aLevel)
       
  1217 		{
       
  1218 		case KSolBtLM:
       
  1219 			rerr = KErrNotSupported;
       
  1220 			break;
       
  1221 			
       
  1222 		case KSolBtACL:
       
  1223 			rerr = DoACLSetOption(aName, aOption);
       
  1224 			break;
       
  1225 			
       
  1226 		default:
       
  1227 			rerr = KErrNotSupported;
       
  1228 			break;
       
  1229 		};
       
  1230 
       
  1231 	return rerr;
       
  1232 	}
       
  1233 
       
  1234 TInt CACLLink::DoACLSetOption(TUint aName, const TDesC8& /*aOption*/)
       
  1235 	{
       
  1236 	LOG_FUNC
       
  1237 	TInt rerr = KErrNone;
       
  1238 	
       
  1239 	switch(aName)
       
  1240 		{
       
  1241 		case KSolBtACLFlushOccured:
       
  1242 			rerr = ProcessFlush();
       
  1243 			break;
       
  1244 		
       
  1245 		default:
       
  1246 			rerr = KErrNotSupported;
       
  1247 			break;
       
  1248 		};
       
  1249 		
       
  1250 	return rerr;
       
  1251 	}
       
  1252 
       
  1253 void CACLLink::RemName(TSockAddr& aAddr) const 
       
  1254 	{
       
  1255 	LOG_FUNC
       
  1256 	//Return the remote name
       
  1257 	// Copy iRemoteDev and iRemotePort into TSockAddr and return
       
  1258 	TACLSockAddr bbAddr(aAddr);
       
  1259 	bbAddr.SetBTAddr(iRemoteDev);
       
  1260 	aAddr=bbAddr;   // Convert back
       
  1261 	}
       
  1262 
       
  1263 void CACLLink::LocalName(TSockAddr& aAddr) const 
       
  1264 	{
       
  1265 	LOG_FUNC
       
  1266 	// Copy iLocalPort into TSockAddr and return
       
  1267 	TACLSockAddr bbAddr(aAddr);
       
  1268 	bbAddr.SetBTAddr(iProtocol.LocalBTAddress());
       
  1269 	aAddr=bbAddr;
       
  1270 	}
       
  1271 
       
  1272 void CACLLink::Start()
       
  1273 	{
       
  1274 	LOG_FUNC
       
  1275 	iState->Start(*this);
       
  1276 	}
       
  1277 
       
  1278 void CACLLink::Timeout(TBasebandTimeout aTimeout)
       
  1279 	{
       
  1280 	LOG_FUNC
       
  1281 	iState->Timeout(*this, aTimeout);
       
  1282 	}
       
  1283 
       
  1284 void CACLLink::AutoBind()
       
  1285 	{
       
  1286 	LOG_FUNC
       
  1287 	// at present no state bothers with this, so just process here
       
  1288 	// do nothing
       
  1289 	}
       
  1290 
       
  1291 void CACLLink::Shutdown(TCloseType aOption)
       
  1292 	{
       
  1293 	LOG_FUNC
       
  1294 	iState->Shutdown(*this, aOption);
       
  1295 	}
       
  1296 
       
  1297 void CACLLink::Shutdown(TCloseType aOption, const TDesC8& /*aDisconnectionData*/)
       
  1298 	{
       
  1299 	LOG_FUNC
       
  1300 	iState->Shutdown(*this, aOption);
       
  1301 	}
       
  1302 
       
  1303 
       
  1304 void CACLLink::NotifyDataToSocket(TUint8 aFlag, const TDesC8& aData)
       
  1305 	{
       
  1306 	LOG_FUNC
       
  1307 	const TUint8 KFlagHeaderSize =1;
       
  1308 /*
       
  1309 	The design of the protocol specification for L2CAP
       
  1310 	means that both we and L2CAP need to know the flag parameter
       
  1311 	for now we just signal one datagram (*could* signal two - one for flag: but that's just as grubby)
       
  1312 */
       
  1313 
       
  1314 
       
  1315 	// make a new chain consisting of Flag(1st octet) followed by Data.
       
  1316 	RMBufChain aclData;
       
  1317 	#ifdef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
  1318 	THCIConnHandle connH=iHandle;
       
  1319 	aclData = const_cast<CHCIFacade&>(iLinksMan.HCIFacade()).TakeInboundACLDataBufferFromPool(connH);
       
  1320 	aclData.CopyIn(aData,KFlagHeaderSize);
       
  1321 	aclData.TrimEnd(aData.Length()+KFlagHeaderSize); //return the reserved MBufs we didn't need
       
  1322 													 //to the global pool
       
  1323 	#else
       
  1324 	TRAPD(err, aclData.CreateL(aData, KFlagHeaderSize));
       
  1325 
       
  1326 	if (err)
       
  1327 		{
       
  1328 		//Since HC->H flow control is off, and we have run out of MBufs
       
  1329 		//there is nothing we can do here but drop or disconnect the link
       
  1330 		//due to limited resources. We drop.
       
  1331 		return;
       
  1332 		}
       
  1333 	#endif
       
  1334 
       
  1335 	aclData.First()->Ptr()[0] = aFlag;	// aData is already in the chain
       
  1336 
       
  1337 
       
  1338 	// slap onto the RMBufPacketQ
       
  1339 	iInboundBuffer.Append(aclData); // transfers
       
  1340 	
       
  1341 
       
  1342 	#ifndef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
  1343 	if (!err)
       
  1344 		{
       
  1345 	#endif
       
  1346 		iSocket->NewData(1);	// datagrams: could async notify - or get l2cap to drain async
       
  1347 	#ifndef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
  1348 		}
       
  1349 	#endif
       
  1350 	}
       
  1351 
       
  1352 
       
  1353 void CACLLink::GetData(TDes8& aDesc,TUint aOptions,TSockAddr* aAddr)
       
  1354 	{
       
  1355 	LOG_FUNC
       
  1356 // see note in call to NewData - we just give a single descriptor
       
  1357 // could get L2CAP to call down with options/addr: it could say whether
       
  1358 // it's expecting flags or not etc
       
  1359 
       
  1360 // this overload is for descriptors - will be deprecated
       
  1361 // for now use a dummy mbufchain
       
  1362 	RMBufChain dummy;
       
  1363 
       
  1364 	GetData(dummy, aDesc.Length(), aOptions, aAddr);
       
  1365 
       
  1366 	aDesc.SetMax();
       
  1367 	dummy.CopyOut(aDesc);
       
  1368 	dummy.Free();	// release the actual mBuf - it's also gone from the inbound buffer collection
       
  1369 	}
       
  1370 
       
  1371 TInt CACLLink::GetData(RMBufChain& aData, TUint /*aLength*/, TUint /*aOptions*/, TSockAddr* /*aAddr*/)
       
  1372 	{
       
  1373 	LOG_FUNC
       
  1374 	static_cast<void>(iInboundBuffer.Remove(aData));	// take off Q
       
  1375 	
       
  1376 	return 1; // datagram
       
  1377 	}
       
  1378 
       
  1379 TUint CACLLink::Write(const TDesC8& aDesc,TUint aOptions, TSockAddr* aAddr)
       
  1380 	{
       
  1381 	LOG_FUNC
       
  1382 	return iState->Write(*this, aDesc, aOptions, aAddr);
       
  1383 	}
       
  1384 
       
  1385 void CACLLink::CloseLogicalLink()
       
  1386 	{
       
  1387 	LOG_FUNC
       
  1388 	// tell our Q controller about ACL death
       
  1389 	iProtocol.ACLController().ACLLogicalLinkDown(iHandle);
       
  1390 	iHandle = KInvalidConnectionHandle;
       
  1391 	}
       
  1392 
       
  1393 void CACLLink::ClearPhysicalLink()
       
  1394 	{
       
  1395 	LOG_FUNC
       
  1396 	CBTBasebandSAP::UnbindLink(EACLLink);
       
  1397 	}
       
  1398 
       
  1399 TInt CACLLink::OpenLogicalLink()
       
  1400 	{
       
  1401 	LOG_FUNC
       
  1402 	// spec says our ACL handle = that of PHY
       
  1403 	iHandle = iPhysicalLink->Handle();
       
  1404 	TInt err = iProtocol.ACLController().ACLLogicalLinkUp(iHandle, iPhysicalLink->IsParked());
       
  1405 
       
  1406 	return err;
       
  1407 	}
       
  1408 
       
  1409 void CACLLink::Error(TInt aErr)
       
  1410 	{
       
  1411 	LOG_FUNC
       
  1412 	iState->Error(*this, aErr);
       
  1413 	}
       
  1414 
       
  1415 void CACLLink::Disconnection()
       
  1416 	{
       
  1417 	LOG_FUNC
       
  1418 	iState->Disconnection(*this);
       
  1419 	}
       
  1420 
       
  1421 void CACLLink::ConnectComplete(const TBTConnect& aConnect)
       
  1422 	{
       
  1423 	LOG_FUNC
       
  1424 	iState->ConnectComplete(*this, aConnect);
       
  1425 	}
       
  1426 
       
  1427 TBool CACLLink::ConnectRequest(const TBTConnect& aConnect, const CPhysicalLink& aPhysicalLink)
       
  1428 	{
       
  1429 	LOG_FUNC
       
  1430 	return iState->ConnectRequest(*this, aConnect, aPhysicalLink);
       
  1431 	}
       
  1432 
       
  1433 void CACLLink::DataReceived(THCIConnHandle __DEBUG_ONLY(aConnH), TUint8 aFlag, const TDesC8& aData)
       
  1434 	{
       
  1435 	LOG_FUNC
       
  1436 	// even if this is broadcast, the data *FROM* the HC to the Host should have
       
  1437 	// the real connection handle of the physical link to the master (who sent the data!)
       
  1438 	__ASSERT_DEBUG(aConnH == Handle(), Panic(EBTACLSAPDataForWrongSAP));
       
  1439 
       
  1440 	if (!CanHandleFlags(aFlag))
       
  1441 		{
       
  1442 		// we can't handle these flags - other ACL SAPs might though!
       
  1443 		return;
       
  1444 		}
       
  1445 
       
  1446 	iState->DataReceived(*this, aFlag, aData);
       
  1447 	}
       
  1448 
       
  1449 void CACLLink::PacketsSent(THCIConnHandle /*aHandle*/, TUint16 /*aNumPackets*/)
       
  1450 	{
       
  1451 	LOG_FUNC
       
  1452 	TryToSend();
       
  1453 	}
       
  1454 	
       
  1455 TBool CACLLink::CanHandleFlags(TUint8 aFlag) const
       
  1456 	{
       
  1457 	LOG_FUNC
       
  1458 	// map packet flags to port
       
  1459 	TUint8 pbFlags = static_cast<TUint8>((aFlag >> KPacketPBBCFlagShift) & KPacketPBFlagMask);
       
  1460 	if ((pbFlags == KFirstHLFragment || pbFlags == KContinuingHLFragment) && iLocalPort == EACLPortL2CAP)
       
  1461 		return ETrue;
       
  1462 	if (pbFlags == 0 && iLocalPort == EACLPortRaw)
       
  1463 		return ETrue;
       
  1464 	return EFalse;
       
  1465 	}
       
  1466 
       
  1467 TInt CACLLink::ProcessFlush()
       
  1468 	{
       
  1469 	LOG_FUNC
       
  1470 	CACLDataQController& aclQCtrl = iProtocol.ACLController();
       
  1471 	return aclQCtrl.SetFlushInProgress(Handle());
       
  1472 	}	
       
  1473 	
       
  1474 TBool CACLLink::IsIdle() const
       
  1475 	{
       
  1476 	LOG_FUNC
       
  1477 	return iState->IsIdle();
       
  1478 	}
       
  1479 
       
  1480 void CACLLink::PhysicalLinkChange(const TBTBasebandEventNotification& aEvent, CPhysicalLink& __DEBUG_ONLY(aPhysicalLink))
       
  1481 	{
       
  1482 	LOG_FUNC
       
  1483 	// ACL logical links only really interested in parking of PHY
       
  1484 	__ASSERT_DEBUG(&aPhysicalLink == iPhysicalLink, Panic(EBTACLSAPWrongPhysicalLink));
       
  1485 
       
  1486 	// test for a park event
       
  1487 	if (aEvent.EventType() & ENotifyParkMode)
       
  1488 		{
       
  1489 		// gone into park, but check phy role: could do broadcast
       
  1490 		iState->Park(*this);
       
  1491 		}
       
  1492 
       
  1493 	else if (aEvent.EventType() & ENotifyActiveMode)
       
  1494 		{
       
  1495 		//un-parked
       
  1496 		iState->Unpark(*this);
       
  1497 		}
       
  1498 
       
  1499 	else 
       
  1500 		{
       
  1501 		// uninteresting event
       
  1502 		}
       
  1503 	}
       
  1504 
       
  1505 void CACLLink::TryToSend()
       
  1506 	{
       
  1507 	LOG_FUNC
       
  1508 	// no need to tell the buffer management entity (acl pool) - already done
       
  1509 	// if socket blocked - unblock
       
  1510 	if (iSocketBlocked)
       
  1511 		{
       
  1512 		iSocketBlocked = EFalse;
       
  1513 		Socket()->CanSend();
       
  1514 		}
       
  1515 	}
       
  1516 
       
  1517 void CACLLink::ParkLogicalLink()
       
  1518 	{
       
  1519 	LOG_FUNC
       
  1520 	iProtocol.ACLController().SetParked(Handle(), ETrue);
       
  1521 	}
       
  1522 
       
  1523 void CACLLink::UnparkLogicalLink()
       
  1524 	{
       
  1525 	LOG_FUNC
       
  1526 	iProtocol.ACLController().SetParked(Handle(), EFalse);
       
  1527 	}
       
  1528 
       
  1529 void CACLLink::SetInitiationState(TInitiationState aState)
       
  1530 	{
       
  1531 	__ASSERT_DEBUG(aState != EInvalidInitiationState, Panic(EBTACLSAPIndeterminateInitiator));
       
  1532 	iInitiationState = aState;
       
  1533 	}
       
  1534 
       
  1535 void CACLLink::ClearInitiationState()
       
  1536 	{
       
  1537 	iInitiationState = EInvalidInitiationState;
       
  1538 	}
       
  1539 
       
  1540 TBool CACLLink::IsLocallyInitiated() const
       
  1541 	{
       
  1542 	__ASSERT_DEBUG(iInitiationState != EInvalidInitiationState, Panic(EBTACLSAPIndeterminateInitiator));
       
  1543 	return iInitiationState == ELocallyInitiated;
       
  1544 	}
       
  1545 
       
  1546 void CACLLink::AccessRequestComplete(TInt aResult)
       
  1547 	{
       
  1548 	// We don't expect the deferred result, if we get this then the state machine
       
  1549 	// for the logical link needs to be updated.
       
  1550 	__ASSERT_DEBUG(aResult != EBTSecManAccessDeferred, Panic(EBTACLSAPUnexpectedSecurityResult));
       
  1551 	if(aResult == EBTSecManAccessDenied) // convert to a symbian error
       
  1552 		{
       
  1553 		aResult = KErrAccessDenied;
       
  1554 		}
       
  1555 	if(aResult != KErrNone)
       
  1556 		{
       
  1557 		// Kill the physical link, this should result in the ACL link being
       
  1558 		// pulled down.
       
  1559 		if(iPhysicalLink)
       
  1560 			{
       
  1561 			iPhysicalLink->Terminate(ERemoteUserEndedConnection);
       
  1562 			}
       
  1563 		}
       
  1564 	// else success from the access requester so we're done.
       
  1565 	}
       
  1566