--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/common/btprt.cpp Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,524 @@
+// 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 file implements the generic interface to a ESOCK PRT
+// for the Bluetooth PRT module
+//
+//
+
+// The Bluetooth protocol family also provides Control-plane facilities
+// thereby relieving the user-plane SAPs and muxers of these duties
+#include <bluetooth/logger.h>
+#include "Avctp.h"
+#include "bt.h"
+#include "linkmgr.h"
+#include "l2cap.h"
+#include "rfcomm.h"
+#include "sdp.h"
+#include "avdtp.h"
+
+#include "IncomingConnListener.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_BT_PRT);
+#endif
+
+#ifdef _DEBUG
+PANICCATEGORY("btprt");
+#endif
+
+_LIT(KBTPrtPanic, "BluetoothPRT Panic");
+
+
+void Panic(TBluetoothFamilyPanic aPanic)
+ {
+ LOG_STATIC_FUNC
+ User::Panic(KBTPrtPanic, aPanic);
+ }
+
+extern "C"
+ {
+ IMPORT_C CProtocolFamilyBase* InstallBTProtocolFamily(); // Force export
+ }
+
+EXPORT_C CProtocolFamilyBase* InstallBTProtocolFamily()
+// Create a new protocol family
+ {
+ LOG_STATIC_FUNC
+ //Return NULL if CBTProtocolFamily::NewL() leaves
+ CProtocolFamilyBase* result=NULL;
+ TRAP_IGNORE(result=CBTProtocolFamily::NewL());
+ return result;
+ }
+
+CBTProtocolFamily* CBTProtocolFamily::NewL()
+ {
+#ifdef __FLOG_ACTIVE
+ CONNECT_LOGGER
+#endif
+ LOG_STATIC_FUNC
+ // Flogging can start after the installation of the Blogger
+ // and the instantiation of the HCI
+ // LOG(_L("+CBTProtocolFamily::NewL"));
+ CBTProtocolFamily* pf= new (ELeave) CBTProtocolFamily();
+ CleanupStack::PushL(pf);
+ pf->ConstructL();
+ CleanupStack::Pop();
+ return pf;
+ }
+
+CBTProtocolFamily::CBTProtocolFamily()
+ : CProtocolFamilyBase(),
+ iBTRefCount(0)
+ {
+ LOG_FUNC
+ }
+
+void CBTProtocolFamily::ConstructL()
+ {
+ LOG_FUNC
+ // install TLS
+ Dll::SetTls(&iBTTls);
+
+ LOG(_L("+CBTProtocolFamily::ConstructL"));
+ iCallback = new (ELeave) CAsyncCallBack(EPriorityHigh);
+ }
+
+CBTProtocolFamily::~CBTProtocolFamily()
+ {
+ LOG_FUNC
+ LOG(_L("+CBTProtocolFamily::~CBTProtocolFamily"));
+ BTSocketTimer::Close();
+ delete iSecurityMgr;
+ delete iCallback;
+ delete iCodServiceMan;
+ iControlPlane.Close();
+ Dll::FreeTls();
+#ifdef __FLOG_ACTIVE
+ CLOSE_LOGGER
+#endif
+ }
+
+
+TInt CBTProtocolFamily::Install()
+ {
+ LOG_FUNC
+
+ TRAPD(err, BTSocketTimer::InitL());
+ return err;
+ }
+
+TInt CBTProtocolFamily::Remove()
+ {
+ LOG_FUNC
+ // set the asynccallback to delete us cleanly
+ return KErrNone;
+ }
+
+TUint CBTProtocolFamily::ProtocolList(TServerProtocolDesc*& aProtocolPointer)
+ {
+ LOG_FUNC
+ // This is cleaned up by ESOCK
+ aProtocolPointer = new TServerProtocolDesc[6];
+
+ if (!aProtocolPointer)
+ return 0;
+
+ // Note it helps if the protocols are defined here in the same order
+ // as in the .esk file or Esock's tags will get mis-assigned.
+
+ CLinkMgrProtocol::ProtocolIdentity(&aProtocolPointer[0]);
+ CL2CAPProtocol::ProtocolIdentity (&aProtocolPointer[1]);
+#ifdef TCI
+ return 2;
+#else // !TCI
+ CRfcommProtocol::ProtocolIdentity (&aProtocolPointer[2]);
+ CSdpProtocol::ProtocolIdentity (&aProtocolPointer[3]);
+#ifndef BLUETOOTH_NO_AV
+ CAvctpProtocol::ProtocolIdentity (&aProtocolPointer[4]);
+ CAvdtpProtocol::ProtocolIdentity (&aProtocolPointer[5]);
+ return 6;
+#else
+ #pragma message("Note: Bluetooth stack will not contain AVCTP or AVDTP");
+ return 4;
+#endif // BLUETOOTH_NO_AV
+#endif // TCI
+ };
+
+CProtocolBase* CBTProtocolFamily::NewProtocolL(TUint /*aSockType*/,TUint aProtocol)
+/**
+ Called by the socket server to create an instance of a new
+ Protocol (layer) of the specified name - must be a subclass of
+ CProtocolBase.
+**/
+ {
+ LOG_FUNC
+
+ // Create the Security mgr
+ if (!iSecurityMgr)
+ {
+ iSecurityMgr = CBTSecMan::NewL();
+ }
+
+ // We create our one instance of our protocols
+ CBluetoothProtocolBase* p = NULL;
+
+ // Create the Cod Service manager with reference to linkmgr
+ if (!iCodServiceMan)
+ {
+ iCodServiceMan = CBTCodServiceMan::NewL(/*reinterpret_cast<CLinkMgrProtocol&>(p)*/);
+ }
+
+
+ switch (aProtocol)
+ {
+ case KBTLinkManager:
+ LOG(_L("CBTProtocolFamily::NewProtocolL - BTLinkMgr"));
+ p = CLinkMgrProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan);
+
+ iCodServiceMan->iLinkMgr = reinterpret_cast<CLinkMgrProtocol*>(p);
+
+ break;
+
+#ifdef TCI
+ case KTCIL2CAP:
+#endif
+ case KL2CAP:
+ LOG(_L("CBTProtocolFamily::NewProtocolL - L2CAP"));
+ p = CL2CAPProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan);
+ break;
+
+#ifndef TCI
+ case KRFCOMM:
+ LOG(_L("CBTProtocolFamily::NewProtocolL - RFCOMM"));
+ p = CRfcommProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan );
+ break;
+
+ case KSDP:
+ LOG(_L("CBTProtocolFamily::NewProtocolL - SDP"));
+ p = CSdpProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan);
+ break;
+ case KAVCTP:
+#ifndef BLUETOOTH_NO_AV
+ LOG(_L("CBTProtocolFamily::NewProtocolL - AVCTP"));
+ p = CAvctpProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan);
+#else
+ LOG(_L("CBTProtocolFamily::NewProtocolL - AVCTP: NOT SUPPORTED, Leaving"));
+ User::Leave(KErrNotSupported);
+#endif //BLUETOOTH_NO_AV
+ break;
+
+ case KAVDTP:
+#ifndef BLUETOOTH_NO_AV
+ LOG(_L("CBTProtocolFamily::NewProtocolL - AVDTP"));
+ p = CAvdtpProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan);
+#else
+ LOG(_L("CBTProtocolFamily::NewProtocolL - AVDTP: NOT SUPPORTED, Leaving"));
+ User::Leave(KErrNotSupported);
+#endif //BLUETOOTH_NO_AV
+ break;
+
+#endif //TCI
+
+ default:
+ User::Leave(KErrArgument);
+ }
+ CleanupStack::PushL(p);
+ iControlPlane.AttachProtocolL(aProtocol, *p);
+ CleanupStack::Pop(p);
+ return p;
+ }
+
+void CBTProtocolFamily::Open()
+ {
+ LOG_FUNC
+ // we don't use the reference-counting of the base-class. We prefer to async close
+ // so we override Open amd implement our own ref counting.
+ iBTRefCount++;
+ }
+
+void CBTProtocolFamily::Close()
+ {
+ LOG_FUNC
+ if(--iBTRefCount <= 0)
+ {
+ iBTRefCount = 0;
+ iCallback->Cancel();
+ // defer calling d'tor
+ TCallBack cb(Destruct, this);
+ iCallback->Set(cb);
+ iCallback->CallBack();
+ }
+ }
+
+/*static*/ TInt CBTProtocolFamily::Destruct(TAny* aProtocolFamily)
+ {
+ LOG_STATIC_FUNC
+ // self-destruct
+ CProtocolFamilyBase* p = reinterpret_cast<CProtocolFamilyBase*>(aProtocolFamily);
+ delete p;
+
+ return EFalse;
+ }
+
+CBluetoothProtocolBase::CBluetoothProtocolBase(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
+: iSecMan(aSecMan), iControlPlane(aControlPlane), iCodMan(aCodMan)
+ {
+ LOG_FUNC
+ }
+
+CBluetoothProtocolBase::~CBluetoothProtocolBase()
+ {
+ LOG_FUNC
+ // detach from control plane
+ ControlPlane().DetachProtocol(*this);
+ delete iListener;
+ }
+
+
+TInt CBluetoothProtocolBase::IncrementListeners()
+/**
+ A protocol object (typically a SAP) has declared that it is listening
+
+ This may mean that the protocol has to provide a bearer-listener
+**/
+ {
+ LOG_FUNC
+ TInt retVal = KErrNone;
+
+ if (!iListeningEntities++)
+ {
+ // need our own listener to bring up lower layers if required for this protocol-level listening SAPs
+ retVal = StartProtocolListening();
+ }
+ return retVal;
+ }
+
+void CBluetoothProtocolBase::DecrementListeners()
+/**
+ A protocol object (typically a SAP) has declared that it is not listening
+
+ This may mean that the protocol can cleanup the bearer-listener
+**/
+ {
+ LOG_FUNC
+ --iListeningEntities;
+ ASSERT_DEBUG(iListeningEntities>=0);
+ if (!iListeningEntities)
+ {
+ // stop protocol listening
+ StopProtocolListening();
+ }
+ }
+
+
+TInt CBluetoothProtocolBase::StartListening(TUint aPort, TUint aSockType, TUint aQueSize, TUid aUid)
+ {
+ LOG_FUNC
+ TRAPD(err, DoStartListeningL(aPort, aSockType, aQueSize, aUid));
+ return err;
+ }
+
+TInt CBluetoothProtocolBase::StartProtocolListening()
+ {
+ LOG_FUNC
+ // protocol doesnt support listening
+ Panic(EBTPrtProtocolCannotListen);
+ return KErrNotSupported;
+ }
+
+// default implementation for stopping a protocol listening
+void CBluetoothProtocolBase::StopProtocolListening()
+ {
+ LOG_FUNC
+ delete iListener;
+ iListener = NULL;
+ }
+
+
+void CBluetoothProtocolBase::DoStartListeningL(TUint aPort, TUint aSockType, TUint aQueSize, TUid aUid)
+ {
+ LOG_FUNC
+ CServProviderBase* sap =iLowerProtocol->NewSAPL(aSockType);
+ iListener=CIncomingConnectionListener::NewL(*this, sap, aPort, aQueSize, aUid);
+ }
+
+TInt CBluetoothProtocolBase::ControlPlaneMessage(TBTControlPlaneMessage /*aMessage*/, TAny* /*aParam*/)
+ {
+ LOG_FUNC
+ __DEBUGGER(); // a C-plane message was targetted for a protocol that didnt implement C-plane stuff
+ return KErrNotSupported;
+ }
+void CBluetoothProtocolBase::Error(TInt /*aError*/,CProtocolBase* /*aSourceProtocol=NULL*/)
+ {
+ LOG_FUNC
+ //Don't do anything, overrides CProtocolBase::Error which causes a Panic
+ }
+void RBTControlPlane::AttachProtocolL(TInt aProtocolNum, CBluetoothProtocolBase& aProtocol)
+/**
+ Called when a protocol is instantiated - allows the Control plane to
+ be aware of it
+**/
+ {
+ LOG_FUNC
+ if (Protocol(aProtocolNum))
+ {
+ User::Leave(KErrAlreadyExists);
+ }
+
+ TBTProtocol protocol;
+ protocol.iProtocolNum = aProtocolNum;
+ protocol.iProtocol = &aProtocol;
+
+ User::LeaveIfError(iProtocols.Append(protocol));
+ }
+
+void RBTControlPlane::DetachProtocol(CBluetoothProtocolBase& aProtocol)
+ {
+ LOG_FUNC
+ for (TInt i=0; i<iProtocols.Count();i++)
+ {
+ if (iProtocols[i].iProtocol == &aProtocol)
+ {
+ iProtocols.Remove(i);
+ break;
+ }
+ }
+ }
+
+void RBTControlPlane::Close()
+ {
+ LOG_FUNC
+ iProtocols.Close();
+ }
+
+
+CBluetoothProtocolBase* RBTControlPlane::Protocol(TInt aProtocolNum) const
+ {
+ LOG_FUNC
+ CBluetoothProtocolBase* p= NULL;
+ for (TInt i=0; i<iProtocols.Count(); i++)
+ {
+ if (iProtocols[i].iProtocolNum == aProtocolNum)
+ p = iProtocols[i].iProtocol;
+ }
+ return p; // does not pass ownership
+ }
+
+/*
+a C-plane message to send a signal to the (possible) SAP handling the physical link
+to the address aAddr
+*/
+TInt RBTControlPlane::ModifyPhysicalLink(TBTControlPlaneMessage aMessage, const TBTDevAddr& aAddr) const
+ {
+ LOG_FUNC
+ // link mgr must be there!
+ CBluetoothProtocolBase* linkmgr = Protocol(KBTLinkManager);
+ ASSERT_DEBUG(linkmgr);
+ return linkmgr->ControlPlaneMessage(aMessage, const_cast<TAny*>(reinterpret_cast<const TAny*>(&aAddr)));
+ }
+
+void RBTControlPlane::TryToAndThenPreventHostEncryptionKeyRefresh(const TBTDevAddr& aAddr, MBluetoothControlPlaneToken*& aOutToken)
+ {
+ LOG_FUNC
+ CBluetoothProtocolBase* linkmgr = Protocol(KBTLinkManager);
+ ASSERT_DEBUG(linkmgr);
+ const TBTDevAddr* addrPtr = &aAddr;
+ TAny* ptr = reinterpret_cast<TAny*>(&addrPtr);
+ TInt err = linkmgr->ControlPlaneMessage(ETryToAndThenPreventHostEncryptionKeyRefresh, ptr);
+ if (err == KErrNone)
+ {
+ aOutToken = *reinterpret_cast<MBluetoothControlPlaneToken**>(ptr);
+ }
+ else
+ {
+ aOutToken = NULL;
+ }
+ }
+
+/*
+a C-plane message to send a message to a target protocol telling them not to authorise a device
+used for multiple protocols taking part in a single use-case that requires only
+one authorisation - eg AVCTP and AVDTP doing A2DP + AVRCP stereo headset
+*/
+TInt RBTControlPlane::Preauthorise(TInt aTargetProtocolNum,
+ const TOverrideAuthorise& aSetPreauthorisation)
+ {
+ LOG_FUNC
+ // either protocol may not be running
+ CBluetoothProtocolBase* target = Protocol(aTargetProtocolNum);
+ if (target)
+ {
+ return target->ControlPlaneMessage(EPreauthoriseDevice, const_cast<TAny*>(reinterpret_cast<const TAny*>(&aSetPreauthorisation)));
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+ }
+
+TPhysicalLinkPresent RBTControlPlane::PhysicalLinkPresent(const TBTDevAddr& aAddr) const
+ {
+ LOG_FUNC
+ // need to stick down a control plane message to ascertain whether a physical channel is in place
+ // linkmgr must be there
+ CBluetoothProtocolBase* linkmgr = Protocol(KBTLinkManager);
+ ASSERT_DEBUG(linkmgr);
+
+ return static_cast<TPhysicalLinkPresent>(
+ linkmgr->ControlPlaneMessage(EPresent,
+ const_cast<TAny*>(reinterpret_cast<const TAny*>(&aAddr))));
+ }
+
+/*
+a C-plane message to send a signal to the (possible) SAP handling the Physical Link(aAddr)
+to add aObserver to its list of subscribers.
+*/
+TInt RBTControlPlane::SubscribePhysicalLink(MPhysicalLinkObserver& aObserver, TBTDevAddr aAddr) const
+ {
+ LOG_FUNC
+ // link mgr must be there!
+ CBluetoothProtocolBase* linkmgr = Protocol(KBTLinkManager);
+ ASSERT_DEBUG(linkmgr);
+
+ TPhysicalLinkSubscriptionInfo subscriptionInfo(aObserver,aAddr);
+
+ return linkmgr->ControlPlaneMessage(ESubscribePhysicalLink, const_cast<TAny*>(reinterpret_cast<const TAny*>(&subscriptionInfo)));
+ }
+
+/*
+a C-plane message to send a signal to the (possible) SAP handling the Physical Link(aAddr)
+to remove aObserver its list of subscribers.
+*/
+TInt RBTControlPlane::UnsubscribePhysicalLink(MPhysicalLinkObserver& aObserver, TBTDevAddr aAddr) const
+ {
+ LOG_FUNC
+ // link mgr must be there!
+ CBluetoothProtocolBase* linkmgr = Protocol(KBTLinkManager);
+ ASSERT_DEBUG(linkmgr);
+
+ TPhysicalLinkSubscriptionInfo subscriptionInfo(aObserver,aAddr);
+
+ return linkmgr->ControlPlaneMessage(EUnsubscribePhysicalLink, const_cast<TAny*>(reinterpret_cast<const TAny*>(&subscriptionInfo)));
+ }
+
+void MBluetoothControlPlaneToken::Release(MBluetoothControlPlaneToken*& aToken)
+ {
+ if(aToken)
+ {
+ aToken->Release();
+ aToken = NULL;
+ }
+ }
+
+