bluetooth/btstack/l2cap/l2cap.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/l2cap/l2cap.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,334 @@
+// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// This implements the CL2CAPProtocol object that is the contact point from
+// BT PRT to the L2cap stack
+// 
+//
+
+#include <bluetooth/logger.h>
+#include <bt_sock.h>
+#include <bluetooth/aclsockaddr.h>
+
+#include "l2cap.h"
+
+#include "l2sapstates.h"
+#include "l2util.h"
+#include "linkmgr.h"
+#include "l2capSAPSignalHandler.h"
+#include "l2sap.h"
+
+
+#ifdef _DEBUG
+#include "L2CapDebugControlInterface.h"
+#endif
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_L2CAP);
+#endif
+
+// Construction & Initialisation
+
+CL2CAPProtocol::CL2CAPProtocol(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
+ : CBluetoothProtocolBase(aSecMan, aControlPlane, aCodMan)
+	{
+	LOG_FUNC
+	TCallBack cb(TryToClose, this);
+	iIdleTimerEntry.Set(cb);
+	}
+
+CL2CAPProtocol::~CL2CAPProtocol()
+	{
+	LOG_FUNC
+	RemoveIdleTimerEntry();
+
+	delete iStateFactory;
+	delete iSigStateFactory;
+	
+	if(LowerProtocol())
+		{
+		LowerProtocol()->Close();
+		}
+
+	// Delete the Mux controller.
+	delete iMuxController;
+
+#ifdef _DEBUG
+	SBtTls* tls = static_cast<SBtTls*>(Dll::Tls());
+	CDebugControlInterface* ptr = tls->iDebugCtrlIF;
+	delete ptr;
+	tls->iDebugCtrlIF = NULL;
+#endif
+
+#ifdef __FLOG_ACTIVE
+	CLOSE_LOGGER
+#endif
+	}
+
+CL2CAPProtocol* CL2CAPProtocol::NewL(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
+	{
+#ifdef __FLOG_ACTIVE
+	CONNECT_LOGGER
+#endif
+	LOG_STATIC_FUNC
+	CL2CAPProtocol* prot = new (ELeave) CL2CAPProtocol(aSecMan, aControlPlane, aCodMan);
+	CleanupStack::PushL(prot);
+	prot->ConstructL();
+	CleanupStack::Pop();
+	return prot;
+	}
+
+void CL2CAPProtocol::ConstructL()
+	{
+	LOG_FUNC
+	iMuxController = new (ELeave) CL2CAPMuxController(*this);	
+	}
+
+void CL2CAPProtocol::InitL(TDesC& /*aTag*/)
+/**
+	Pre-binding initialise.
+	Allocate any objects we need here.
+	The socket ensures that this function will only be called once per
+	object of this class, regardless of how long it hangs around.
+**/
+	{
+	LOG_FUNC
+	// Init 
+	__ASSERT_DEBUG(!iClosePending, Panic(EL2CAPProtocolOpenedAfterClose));
+	__ASSERT_DEBUG(!iIdleEntryQueued, Panic(EL2CAPProtocolOpenedAfterClose));
+	__ASSERT_DEBUG(!iStateFactory, Panic(EL2CAPProtocolOpenedAfterClose));
+	__ASSERT_DEBUG(!iSigStateFactory, Panic(EL2CAPProtocolOpenedAfterClose));
+
+	// Create all the things we need now
+	LOG(_L("L2CAP : Initialising states"));
+	iStateFactory=CL2CAPSAPStateFactory::NewL();
+	iSigStateFactory=CL2CAPSignalStateFactory::NewL();
+	LOG(_L("L2CAP : Initialising complete"));
+
+#ifdef _DEBUG
+	SBtTls* tls = static_cast<SBtTls*>(Dll::Tls());
+	tls->iDebugCtrlIF = CDebugControlInterface::NewL();
+#endif
+	}
+
+
+void CL2CAPProtocol::StartL()
+/**
+	Binding complete.
+	Startup call from socket.  Do nothing
+**/
+	{
+	LOG_FUNC
+	}
+
+// From higher protocol
+void CL2CAPProtocol::BindL(CProtocolBase* /*aProtocol*/, TUint /*aId*/)
+	{
+	// Could register the protocol that's bound to us
+	LOG_FUNC
+	}
+
+void CL2CAPProtocol::BindToL(CProtocolBase* aProtocol)
+	{
+	LOG_FUNC
+#ifdef _DEBUG
+	TServerProtocolDesc prtDesc;
+	aProtocol->Identify(&prtDesc);
+
+	if(prtDesc.iAddrFamily!=KBTAddrFamily ||
+	   prtDesc.iProtocol!=KBTLinkManager)
+		{
+		LEAVEL(KErrBtEskError);
+		}
+#endif
+	aProtocol->BindL(this, 0);
+	aProtocol->Open();
+	iLowerProtocol = static_cast<CBluetoothProtocolBase*>(aProtocol);
+	}
+
+// Factory functions
+CServProviderBase* CL2CAPProtocol::NewSAPL(TUint aSockType)
+/** 
+	Create a new SAP.
+	The SAP returned is owned by the caller -- this protocol will not clean it up.
+	The socket uses this function to create a new SAP, and the socket will delete when it
+	is finished with it.
+**/
+	{
+	LOG_FUNC
+	
+	CL2CAPConnectionSAP* lsap = NULL;
+		
+	switch(aSockType)
+		{
+	case KSockSeqPacket:  // packet interface
+		lsap=CL2CAPConnectionSAP::NewL(*this);
+		break;
+	default:
+		LEAVEL(KErrNotSupported);
+		break;
+		}
+
+	return lsap;
+	}
+
+// Query functions
+
+void CL2CAPProtocol::Identify(TServerProtocolDesc *aDesc)const
+//
+// Identify request from SOCKET server
+//
+	{
+	LOG_FUNC
+	CL2CAPProtocol::ProtocolIdentity(aDesc);
+	}
+
+void CL2CAPProtocol::ProtocolIdentity(TServerProtocolDesc* aDesc)
+	{
+	LOG_STATIC_FUNC
+	_LIT(name,"L2CAP");
+	aDesc->iProtocol=KL2CAP;
+	aDesc->iName=name;
+	aDesc->iAddrFamily=KBTAddrFamily;
+	aDesc->iSockType=KSockSeqPacket;
+	
+	aDesc->iVersion=TVersion(KBTMajor,KBTMinor,KBTBuild);
+	aDesc->iByteOrder=ELittleEndian;
+	aDesc->iServiceInfo=KL2CAPSeqPacketServiceInfo;
+	aDesc->iNamingServices=0;
+	aDesc->iSecurity=KSocketNoSecurity;
+	aDesc->iMessageSize=KSocketMessageSizeNoLimit; //This is the MAX packet size.
+	aDesc->iServiceTypeInfo=ESocketSupport|ETransport|EPreferMBufChains|ENeedMBufs|EUseCanSend;
+	aDesc->iNumSockets=KL2CAPSockets;
+	}
+
+void CL2CAPProtocol::CloseNow()
+/**
+	Close command from base class.
+	Called when ref count reaches 0.
+	We don't actually have to close now, but when we finally
+	do, we must call CanClose (done within TryToClose). That will
+	actually delete us. In the mean time, if a new client tries
+	to connect to L2CAP, the socket will use this existing one and just
+	call Open on it.
+	What we do here, is queue an idle timer entry. It's expiry will
+	call TryToClose, which will actually do the close.
+**/
+	{
+	LOG_FUNC
+	iClosePending = ETrue;
+	QueIdleTimerEntry();
+	}
+
+void CL2CAPProtocol::Open()
+/**
+	Open L2CAP protocol.
+	Called every time a new client (of L2CAP) wants to use it.
+**/
+	{
+	LOG_FUNC
+	iClosePending = EFalse;
+	RemoveIdleTimerEntry();
+	CProtocolBase::Open();
+	}
+
+void CL2CAPProtocol::Close()
+	{
+	LOG_FUNC
+	CProtocolBase::Close();
+	}
+
+void CL2CAPProtocol::QueIdleTimerEntry()
+/**
+	Queue idle timer entry.
+	When this timer expires, it'll call TryToClose, which actually
+	causes the thing to finally close down.
+**/
+	{
+	LOG_FUNC
+	RemoveIdleTimerEntry();
+	iIdleEntryQueued = ETrue;
+	BTSocketTimer::Queue(KL2ProtocolIdleTimeout*KL2ProtocolSecondTimerMultiplier, iIdleTimerEntry);
+	}
+
+void CL2CAPProtocol::RemoveIdleTimerEntry()
+/**
+	Called whenever we're opened.
+	Checks there are no idle timer entries queued.
+**/
+	{
+	LOG_FUNC
+	if (!iIdleEntryQueued)
+		return;
+	BTSocketTimer::Remove(iIdleTimerEntry);
+	iIdleEntryQueued = EFalse;
+	}
+
+void CL2CAPProtocol::TryToClose()
+	{
+	LOG_FUNC
+	if (!iIdleEntryQueued && iClosePending && MuxController().CanProtocolClose())
+		{
+		CanClose();
+		}
+	}
+
+TInt CL2CAPProtocol::TryToClose(TAny* aProtocol)
+/*
+	Actually try to close the protocol.
+	Called after the idle timeout period by the BTSocketTimer. If
+	we're all set to close down, the thing is closed.
+*/
+	{
+	LOG_STATIC_FUNC
+	CL2CAPProtocol* p=static_cast<CL2CAPProtocol*>(aProtocol);
+	p->iIdleEntryQueued = EFalse;
+	p->TryToClose();
+	return EFalse;
+	}
+
+CL2CAPSAPStateFactory& CL2CAPProtocol::StateFactory() const
+	{
+	LOG_FUNC
+	return *iStateFactory;
+	}
+
+CL2CAPSignalStateFactory& CL2CAPProtocol::SigStateFactory() const
+	{
+	LOG_FUNC
+	return *iSigStateFactory;
+	}
+
+TInt CL2CAPProtocol::BearerConnectComplete(const TBTDevAddr& aAddr, CServProviderBase* aSAP)
+	{
+	LOG_FUNC
+	return iMuxController->BearerConnectComplete(aAddr, aSAP);
+	}
+
+const TBTDevAddr& CL2CAPProtocol::LocalBTAddr() const
+	{
+	LOG_FUNC
+	return static_cast<CLinkMgrProtocol*>(iLowerProtocol)->LocalBTAddress();
+	}
+
+TInt CL2CAPProtocol::StartProtocolListening()
+// forward L2CAPs listening requirements to listener
+	{
+	LOG_FUNC
+	return CBluetoothProtocolBase::StartListening(EACLPortL2CAP,
+												  KSockBluetoothTypeACL,
+												  KL2CAPIncomingConnQueueSize,
+												  KUidServiceL2CAP);
+	}
+
+