bluetooth/btstack/avdtp/avdtpLogicalChannelFactory.h
changeset 0 29b1cd4cb562
--- /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