--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/avdtp/avdtpLogicalChannelFactory.h Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,462 @@
+// Copyright (c) 2003-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:
+// Defines the avdtp logical channel factory
+// which creates the logical (L2CAP) channels for transport and signalling channels
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include <bt_sock.h>
+#include <es_prot.h>
+
+#ifndef AVDTPLOGICALCHANNELFACTORY_H
+#define AVDTPLOGICALCHANNELFACTORY_H
+
+#include "avdtpAllocators.h"
+
+class XLogicalChannelFactoryClient;
+class CManagedLogicalChannel;
+class CProtocolBase;
+struct TLogicalChannelRecord;
+class CLogicalChannelFactory;
+class CBluetoothProtocolBase;
+
+const TInt KInitialSequenceNumber = 1;
+const TInt KAvdtpChannelArraySize = 3;
+
+typedef TInt8 TLogicalChannelFactoryRequestId;
+
+
+NONSHARABLE_CLASS(TRequestIdManager) : public TBitFieldAllocator
+ {
+public:
+ inline TInt GetId(TLogicalChannelFactoryRequestId& aId);
+ inline void FreeId(TLogicalChannelFactoryRequestId aId);
+ };
+
+// abstract
+NONSHARABLE_CLASS(CLogicalChannelFactoryRequest) : public CBase
+ {
+friend class CLogicalChannelFactory;
+protected:
+ CLogicalChannelFactoryRequest(XLogicalChannelFactoryClient& aClient, TLogicalChannelFactoryRequestId aId);
+ XLogicalChannelFactoryClient& iClient;
+ TSglQueLink iFactoryQLink;
+ TLogicalChannelFactoryRequestId iId;
+ TInt iNumChannelsRequired; // those left to connect
+ };
+
+// abstract
+NONSHARABLE_CLASS(CLogicalChannelFactoryPassiveRequest) : public CLogicalChannelFactoryRequest
+ {
+public:
+ ~CLogicalChannelFactoryPassiveRequest();
+protected:
+ CLogicalChannelFactoryPassiveRequest(XLogicalChannelFactoryClient& aClient,
+ TLogicalChannelFactoryRequestId aId,
+ CBluetoothProtocolBase& aAvdtp);
+ void BaseConstructL();
+private:
+ CBluetoothProtocolBase& iAvdtp;
+ };
+
+NONSHARABLE_CLASS(CExpectSignallingLogicalChannel) : public CLogicalChannelFactoryPassiveRequest
+ {
+public:
+ static CExpectSignallingLogicalChannel* NewL(XLogicalChannelFactoryClient& aClient, TLogicalChannelFactoryRequestId aId, CBluetoothProtocolBase& aAvdtp);
+private:
+ void ConstructL();
+ CExpectSignallingLogicalChannel(XLogicalChannelFactoryClient& aClient, TLogicalChannelFactoryRequestId aId, CBluetoothProtocolBase& aAvdtp);
+ };
+/**
+Use to tell factory to expect explicitly sequenced logical channels, typically used for Direct Transport channels
+*/
+NONSHARABLE_CLASS(CExpectSessionLogicalChannels) : public CLogicalChannelFactoryPassiveRequest
+ {
+public:
+ static CExpectSessionLogicalChannels* NewL(XLogicalChannelFactoryClient& aClient, TLogicalChannelFactoryRequestId aId,
+ TInt aNumRequired, CBluetoothProtocolBase& aAvdtp);
+private:
+ void ConstructL();
+ CExpectSessionLogicalChannels(XLogicalChannelFactoryClient& aClient, TLogicalChannelFactoryRequestId aId,
+ TInt aNumRequired, CBluetoothProtocolBase& aAvdtp);
+ };
+
+/**
+For clients to issue requests to the ChannelFactory
+*/
+NONSHARABLE_CLASS(CLogicalChannelFactoryActiveRequest) : public CLogicalChannelFactoryRequest
+ {
+friend class CLogicalChannelFactory;
+public:
+ ~CLogicalChannelFactoryActiveRequest();
+protected:
+ CLogicalChannelFactoryActiveRequest(const TBTDevAddr& aAddr, XLogicalChannelFactoryClient& aClient, TLogicalChannelFactoryRequestId aId);
+protected:
+ TFixedArray<CManagedLogicalChannel*, KAvdtpChannelArraySize> iLogicalChannels;
+ TBTDevAddr iRemoteDev;
+ };
+
+NONSHARABLE_CLASS(CCreateSignallingLogicalChannel) : public CLogicalChannelFactoryActiveRequest
+ {
+public:
+ static CCreateSignallingLogicalChannel* NewL(const TBTDevAddr&,
+ XLogicalChannelFactoryClient& aClient,
+ TLogicalChannelFactoryRequestId aId,
+ CLogicalChannelFactory& aLogicalChannelFactory);
+
+ static CCreateSignallingLogicalChannel* NewLC(const TBTDevAddr&,
+ XLogicalChannelFactoryClient& aClient,
+ TLogicalChannelFactoryRequestId aId,
+ CLogicalChannelFactory& aLogicalChannelFactory);
+private:
+ CCreateSignallingLogicalChannel(const TBTDevAddr&, XLogicalChannelFactoryClient& aClient, TLogicalChannelFactoryRequestId aId);
+ void ConstructL(CLogicalChannelFactory& aLogicalChannelFactory);
+ };
+
+
+/**
+To create n logical channels
+*/
+NONSHARABLE_CLASS(CCreateSessionLogicalChannels) : public CLogicalChannelFactoryActiveRequest
+ {
+public:
+ static CCreateSessionLogicalChannels* NewL(const TBTDevAddr& aAddr, XLogicalChannelFactoryClient& aClient,
+ TLogicalChannelFactoryRequestId aId, TInt aNumRequired);
+ static CCreateSessionLogicalChannels* NewLC(const TBTDevAddr& aAddr, XLogicalChannelFactoryClient& aClient,
+ TLogicalChannelFactoryRequestId aId, TInt aNumRequired);
+private:
+ CCreateSessionLogicalChannels(const TBTDevAddr& aAddr, XLogicalChannelFactoryClient& aClient,
+ TLogicalChannelFactoryRequestId aId, TInt aNumRequired);
+ };
+
+/**
+To close logical channels
+*/
+NONSHARABLE_CLASS(CCloseSessionLogicalChannels) : public CLogicalChannelFactoryRequest
+ {
+friend class CLogicalChannelFactory;
+public:
+ static CCloseSessionLogicalChannels* NewL(XLogicalChannelFactoryClient& aClient,
+ TLogicalChannelFactoryRequestId aId);
+ static CCloseSessionLogicalChannels* NewLC(XLogicalChannelFactoryClient& aClient,
+ TLogicalChannelFactoryRequestId aId);
+ ~CCloseSessionLogicalChannels();
+
+ void StartJob(TInt aTimeout);
+ void ChannelClosed(CManagedLogicalChannel* aChannel);
+private:
+ CCloseSessionLogicalChannels(XLogicalChannelFactoryClient& aClient,
+ TLogicalChannelFactoryRequestId aId);
+ static TInt WatchdogBarked(TAny* aCloseLogicalChannels);
+ void CloseChannels(TBool aNotifyCompletion);
+
+private:
+ TFixedArray<CManagedLogicalChannel*, KAvdtpChannelArraySize> iLogicalChannels;
+ TDeltaTimerEntry iTimerEntry;
+ };
+
+#ifdef _DEBUG
+#define DEBUG_STORE_FACTORY_REQUEST iChannelFactoryRequest = &\
+
+#else
+#define DEBUG_STORE_FACTORY_REQUEST
+#endif
+
+/**
+Class representing the job the factory has undertaken
+This is always returned synchronously - the client should inspect if the job has been completed synchronously
+via the State() method.
+If the job is process asynchronously then a new one is returned upon completion
+*/
+NONSHARABLE_CLASS(TLogicalChannelFactoryTicket)
+ {
+friend class CLogicalChannelFactory;
+public:
+ enum TLogicalChannelFactoryRequestState
+ {
+ ERequestIdle,
+ ERequestOutstanding,
+ ERequestComplete,
+ ERequestErrored
+ };
+
+ TLogicalChannelFactoryTicket(CLogicalChannelFactory* aFactory, TLogicalChannelFactoryRequestId aId);
+ TLogicalChannelFactoryTicket();
+ TLogicalChannelRecord GetLogicalChannel(TInt aSequenceNumber=1);
+
+ inline TLogicalChannelFactoryRequestState State() const { return iState; }
+ inline TLogicalChannelFactoryRequestId Id() const { return iId; }
+
+private:
+ void SetState(TLogicalChannelFactoryRequestState aNewState);
+
+private:
+ CLogicalChannelFactory* iFactory; // non-owned, cannot be reference in default ctor
+ TLogicalChannelFactoryRequestId iId;
+ TLogicalChannelFactoryRequestState iState;
+ };
+
+
+/*
+The class provides a callback for someone that asked for logical channels
+@note this is an X class (see Programming DB) as it is effectively an M-class
+but must have a member to be que-able.
+*/
+NONSHARABLE_CLASS(XLogicalChannelFactoryClient)
+ {
+public:
+ virtual void LogicalChannelFactoryRequestComplete(TLogicalChannelFactoryTicket, TInt aResult)=0;
+ TSglQueLink iFactoryQLink;
+ };
+
+
+/**
+Knows about ordering of L2CAP channels
+Hands ownership of newly established channels to clients
+Provides them with the TransportSession to
+ a) remind them
+ b) to assert it's ok
+
+The use of this class will to some extent be by someone who
+additionally knows (or is implcitily designed as such) of the
+channel order - for we cannot go adding a reporting bearer merely
+to obtain a recovery bearer....(presumably :o)
+
+Once ownership is transferred the caller will synchronously have to set
+itself as the SocketNotify of the L2CAP SAP
+@internalComponent
+*/
+class CDirectChannel;
+NONSHARABLE_CLASS(CLogicalChannelFactory) : public CBase, public MSocketNotify, public XLogicalChannelFactoryClient
+ {
+friend class TLogicalChannelFactoryTicket;
+public:
+ static CLogicalChannelFactory* NewL(CBluetoothProtocolBase& iProtocol, CProtocolBase& aSAPFactory);
+
+ TLogicalChannelFactoryTicket CreateSignallingLogicalChannelL(const TBTDevAddr& aAddr,
+ XLogicalChannelFactoryClient& aClient);
+
+ TLogicalChannelFactoryTicket CreateSessionLogicalChannelsL(const TBTDevAddr& aAddr,
+ XLogicalChannelFactoryClient& aClient, TInt aNumRequired);
+
+ void CloseSessionLogicalChannelsL(TArray<CDirectChannel*>& aChannels,
+ TInt aTimeout);
+
+ TLogicalChannelFactoryTicket ExpectSignallingLogicalChannelL(XLogicalChannelFactoryClient& aClient);
+
+ TLogicalChannelFactoryTicket ExpectSessionLogicalChannelsL(XLogicalChannelFactoryClient& aClient,
+ TInt aNumRequired);
+
+ void LogicalChannelLost(CManagedLogicalChannel* aChannel);
+ void Cancel(TLogicalChannelFactoryTicket& aJobSpec);
+ ~CLogicalChannelFactory();
+ inline CProtocolBase& SAPFactory() const;
+ TInt BearerConnectComplete(const TBTDevAddr& /*aAddr*/,
+ CServProviderBase* aSAP); // forward from AVDTP protocol when listen complete
+private:
+// from MSocketNotify
+ virtual void NewData(TUint aCount);
+ virtual void CanSend();
+ virtual void ConnectComplete();
+ virtual void ConnectComplete(const TDesC8& aConnectData);
+ virtual void ConnectComplete(CServProviderBase& aSSP);
+ virtual void ConnectComplete(CServProviderBase& aSSP,const TDesC8& aConnectData);
+ virtual void CanClose(TDelete aDelete=EDelete);
+ virtual void CanClose(const TDesC8& aDisconnectData,TDelete aDelete=EDelete);
+ virtual void Error(TInt aError,TUint aOperationMask=EErrorAllOperations);
+ virtual void Disconnect();
+ virtual void Disconnect(TDesC8& aDisconnectData);
+ virtual void IoctlComplete(TDesC8* aBuf);
+ virtual void NoBearer(const TDesC8& aConnectionInfo);
+ virtual void Bearer(const TDesC8& aConnectionInfo);
+
+private:
+// from XLogicalChannelFactoryClient
+ virtual void LogicalChannelFactoryRequestComplete(TLogicalChannelFactoryTicket, TInt aResult);
+
+private:
+ CLogicalChannelFactory(CBluetoothProtocolBase& iProtocol, CProtocolBase& aSAPFactory);
+ void ConstructL();
+ void DoObtainChannelL();
+ static TInt TryNextJob(TAny* aAny);
+ void TryNextActiveJob();
+ TBool CheckActiveJobComplete(CLogicalChannelFactoryActiveRequest& aJob);
+ void CompleteActiveJob(TInt aError);
+ void NotifyComplete(TInt aError, CLogicalChannelFactoryRequest& aRequest);
+ void SetId(CLogicalChannelFactoryActiveRequest& aRequest);
+ static void FreeId(TAny* aId);
+ void DeleteRequest(CLogicalChannelFactoryRequest *aRequest);
+
+ TLogicalChannelRecord ClaimLogicalChannel(TInt aSequenceNumber, TLogicalChannelFactoryRequestId aId, TBool& aFinished);
+ CManagedLogicalChannel* FindUnclaimedLogicalChannel(const TBTDevAddr& aAddr,
+ TInt aSequenceNumber,
+ TLogicalChannelFactoryRequestId& aId);
+ TInt TryToTakeConnection(const TBTDevAddr& aRemote, CServProviderBase* aSAP,
+ TSglQue<CLogicalChannelFactoryPassiveRequest>& aJobQueue);
+
+private:
+ CBluetoothProtocolBase& iProtocol; //AVDTP
+ CProtocolBase& iBearerSAPFactory; //L2CAP
+ TDblQue<CManagedLogicalChannel> iUnclaimedLogicalChannels;
+ TSglQue<CLogicalChannelFactoryActiveRequest> iPendingActiveJobs;
+ TSglQue<CLogicalChannelFactoryPassiveRequest> iPendingPassiveSignallingJobs;
+ TSglQue<CLogicalChannelFactoryPassiveRequest> iPendingPassiveSessionJobs;
+ TSglQue<CCloseSessionLogicalChannels> iCloseChannelJobs;
+ CLogicalChannelFactoryActiveRequest* iCurrentActiveJob;
+ TBool iCurrentJobCancelled;
+ TRequestIdManager iIdManager;
+ TLogicalChannelFactoryRequestId iId; // used for cleaning up if the got (getid) is to be lost due to a leave
+ CAsyncCallBack* iAsyncTryNextJob;
+ };
+
+
+NONSHARABLE_CLASS(CManagedLogicalChannel) : public CBase, public MSocketNotify
+/**
+ for queuing inbound unclaimed SAPs. needs to be a socket so that SAP
+ can declare newdata, disconnection etc.
+*/
+ {
+friend class CLogicalChannelFactory; //for quing
+public:
+ static CManagedLogicalChannel* NewL(CLogicalChannelFactory& aFactory,
+ const TBTDevAddr& aAddr,
+ TInt aSequenceNumber,
+ TLogicalChannelFactoryRequestId aId,
+ CServProviderBase* aSAP = NULL);
+ static CManagedLogicalChannel* NewL(CLogicalChannelFactory& aFactory,
+ TLogicalChannelFactoryRequestId aId);
+
+ ~CManagedLogicalChannel();
+
+ void Shutdown();
+
+private:
+// from MSocketNotify
+ virtual void NewData(TUint aCount);
+ virtual void CanSend();
+ virtual void ConnectComplete();
+ virtual void ConnectComplete(const TDesC8& aConnectData);
+ virtual void ConnectComplete(CServProviderBase& aSSP);
+ virtual void ConnectComplete(CServProviderBase& aSSP,const TDesC8& aConnectData);
+ virtual void CanClose(TDelete aDelete=EDelete);
+ virtual void CanClose(const TDesC8& aDisconnectData,TDelete aDelete=EDelete);
+ virtual void Error(TInt aError,TUint aOperationMask=EErrorAllOperations);
+ virtual void Disconnect();
+ virtual void Disconnect(TDesC8& aDisconnectData);
+ virtual void IoctlComplete(TDesC8* aBuf);
+ virtual void NoBearer(const TDesC8& aConnectionInfo);
+ virtual void Bearer(const TDesC8& aConnectionInfo);
+
+private:
+ CManagedLogicalChannel(CLogicalChannelFactory& aFactory,
+ const TBTDevAddr& aAddr,
+ TInt aSequenceNumber,
+ TLogicalChannelFactoryRequestId aId);
+
+ CManagedLogicalChannel(CLogicalChannelFactory& aFactory,
+ TLogicalChannelFactoryRequestId aId);
+
+ void ConstructL(CServProviderBase* aPrecreatedSAP);
+ CServProviderBase* ObtainSAP();
+ void ProvideSAP(CServProviderBase* aSAP);
+
+private:
+ CLogicalChannelFactory& iFactory;
+ TBTDevAddr iRemoteAddress;
+ TInt iSequenceNumber; // for sequence creations/MCs
+ CServProviderBase* iLogicalChannelSAP;
+ TUint iDataCount;
+ TBool iEndOfData; // bit annoying, but safer that bittwiddling on iDataCount
+ TDblQueLink iFactoryQLink;
+ TLogicalChannelFactoryRequestId iId; // the request this was part of
+ };
+
+inline TInt TRequestIdManager::GetId(TLogicalChannelFactoryRequestId& aId)
+ {
+ TInt val, res;
+ res = Get(val, 30, 1); // 0 is "invalid"
+ aId = static_cast<TLogicalChannelFactoryRequestId>(val);
+ return res;
+ }
+
+inline void TRequestIdManager::FreeId(TLogicalChannelFactoryRequestId aId)
+ {
+ Free(aId);
+ }
+
+ inline CProtocolBase& CLogicalChannelFactory::SAPFactory() const
+ {
+ return iBearerSAPFactory;
+ }
+
+NONSHARABLE_CLASS(TLogicalChannelRecord)
+/*
+Effectively a struct for transferring ownership of resulting logical channels
+Binds together the SAP, and any data count that has appeared whilst the logical channel
+lay unclaimed.
+*/
+ {
+public:
+ inline TLogicalChannelRecord();
+ inline void Reset();
+public:
+ CServProviderBase* iLogicalChannelSAP; // non-owned
+ TUint iDataCount;
+ TBool iEndOfData; // bit annoying, but safer that bittwiddling on iDataCount
+ };
+
+/**
+To help claim logical channels
+*/
+NONSHARABLE_CLASS(TLogicalChannelFactoryTicketInspector)
+ {
+public:
+ TLogicalChannelFactoryTicketInspector(TLogicalChannelFactoryTicket& aTicket,
+ TBool aRequireReporting,
+ TBool aRequireRecovery,
+ TBool aMuxed);
+ TLogicalChannelRecord GetLogicalChannel(TAvdtpTransportSessionType aType);
+private:
+ TLogicalChannelFactoryTicket& iTicket;
+ const TInt iSignallingSequenceNumber;
+ const TInt iMediaSequenceNumber; // always first whether muxed or not
+ TInt iReportingSequenceNumber;
+ TInt iRecoverySequenceNumber;
+ TLogicalChannelRecord iCachedRecord; // eg for Reporting which is the same LC as media
+ TBool iCached;
+#ifdef _DEBUG
+ TBool iRequireReporting;
+ TBool iRequireRecovery;
+#endif
+ };
+
+
+inline TLogicalChannelRecord::TLogicalChannelRecord()
+ {
+ Reset();
+ }
+
+inline void TLogicalChannelRecord::Reset()
+ {
+ iLogicalChannelSAP = NULL;
+ iDataCount = 0;
+ iEndOfData = EFalse;
+ }
+
+#endif //AVDTPLOGICALCHANNELFACTORY_H