sl@0: // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #ifndef __GAVDPSTATEMACHINE_H__ sl@0: #define __GAVDPSTATEMACHINE_H__ sl@0: sl@0: #include <e32base.h> sl@0: #include <bttypes.h> //TBTDevAddr sl@0: #include <es_sock.h> //RSocketServer, RSocket sl@0: #include <gavdp.h> //MGavdpUser, RGavdp sl@0: #include <bluetoothav.h> //TAvdtpSEPInfo, TSEID sl@0: #include <mmf/common/mmfutilities.h> //TFourCC sl@0: #include <mmf/server/sounddevice.h> //TMMFStereoSupport sl@0: #include "GavdpStates.h" sl@0: sl@0: sl@0: const TUint KGAVDPCallbackTimeout = 30000000; sl@0: sl@0: class CGavdpTimeout; //fwd ref sl@0: class CA2dpAudioCodecConfiguration; sl@0: sl@0: using namespace SymbianSBC; sl@0: using namespace SymbianBluetoothAV; sl@0: sl@0: /** sl@0: structure used internally in the GAVDP state machine to keep sl@0: track of seps than can be used on the headset to send audio and sl@0: the local symbian device SEPs sl@0: */ sl@0: struct TUsableSEP sl@0: { sl@0: TSEID iSEID; sl@0: TFourCC iDataType; sl@0: }; sl@0: sl@0: /** sl@0: Callback class implemented by CA2dpBTHeadsetAudioInterface to get events sl@0: back from CGAVDPStateMachine sl@0: */ sl@0: class MGAVDPStateChangeObserver sl@0: { sl@0: public: sl@0: /** sl@0: Callback when the CGAVDPStateMachine has completed a state change sl@0: initiated by a call to ChangeState sl@0: sl@0: @internalComponent sl@0: @param aInitialState The state the CGAVDPStateMachine prior to calling ChangeState sl@0: @param standard SymbianOS error sl@0: */ sl@0: void virtual GAVDPStateChangeComplete(const TGAVDPState& aInitialState, TInt aError) = 0; sl@0: sl@0: /** sl@0: Callback when the GAVDPStateMachine detects an error condition sl@0: event while no state change is in progress sl@0: sl@0: @internalComponent sl@0: @param aError standard SymbianOS error sl@0: */ sl@0: void virtual GAVDPStateMachineEvent(TInt aError) = 0; sl@0: sl@0: /** sl@0: Callback when the headset suspends the streaming sl@0: sl@0: @internalComponent sl@0: */ sl@0: void virtual GAVDPStateMachineStreamSuspendedByRemoteHeadset() = 0; sl@0: sl@0: /** sl@0: Callback when the headset requested a reconfiguration of the settings sl@0: sl@0: @internalComponent sl@0: @return an error code indicating whether it was possible to perform the reconfiguration sl@0: */ sl@0: TInt virtual GAVDPStateMachineReconfigureByRemoteHeadset() = 0; sl@0: sl@0: /** sl@0: Callback when the headset starts (or restarts) the streaming sl@0: sl@0: @internalComponent sl@0: */ sl@0: void virtual GAVDPStateMachineStreamResumedByRemoteHeadset() = 0; sl@0: }; sl@0: sl@0: sl@0: /** sl@0: GAVDP state machine used by the CA2dpBTHeadsetAudioInterface. sl@0: This class is used by the CA2dpBTHeadsetAudioInterface to sl@0: initialize and open the headset, which involved finding SEPs, sl@0: configuring , getting a bearer and streaming. The CGAVDPStateMachine sl@0: uses the MGAVDPStateChangeObserver callback to inform the CA2dpBTHeadsetAudioInterface sl@0: of when the state change is complete, error conditions, and state changes sl@0: initiated by the headset itself sl@0: sl@0: @internalComponent sl@0: */ sl@0: NONSHARABLE_CLASS(CGAVDPStateMachine) : public CActive, public MGavdpUser sl@0: { sl@0: friend class CGavdpTimeout; sl@0: public: sl@0: static CGAVDPStateMachine* NewL(MGAVDPStateChangeObserver& aGAVDPStateChangeObserver, CA2dpAudioCodecConfiguration& aA2dpCodecSettings, RSocketServ& aSocketServer); sl@0: ~CGAVDPStateMachine(); sl@0: void SetBTAddress(const TBTDevAddr& aRemoteAddress); sl@0: TInt Reconfigure(TBool aSettingsHaveChanged); sl@0: TInt ChangeState(const TGAVDPState& aNewState); sl@0: void CancelChangeState(); //external request to cancel state change sl@0: TGAVDPState State() const; sl@0: RArray<TUsableSEP>& UsableSEPs() const; sl@0: RSocket& BearerSocket() const; sl@0: TBTDevAddr& BTAddress() const; sl@0: TInt CodecCaps(TAvdtpMediaCodecCapabilities*& aCodecCaps) const; sl@0: sl@0: //used by a2dp instead of CodecCaps sl@0: TAvdtpMediaCodecCapabilities* RemoteCodecConfiguration(); sl@0: private: sl@0: CGAVDPStateMachine(MGAVDPStateChangeObserver& aGAVDPStateChangeObserver, CA2dpAudioCodecConfiguration& aA2dpCodecSettings, RSocketServ& aSocketServer); sl@0: void ConstructL(); sl@0: TInt RegisterLocalSEP(); sl@0: void ConnectToGAVDP(); sl@0: void DiscoverRemoteSEPs(); sl@0: void GetRemoteSEPCapability(); sl@0: void GetRemoteSEPCapabilities(); sl@0: void ConfigureSEP(); sl@0: TInt ConfigureLocalSEP(); sl@0: TInt ConfigureRemoteSEP(); sl@0: void CreateBearerSocket(); sl@0: void StartStream(); sl@0: void SuspendStream(); sl@0: sl@0: void NextState(); sl@0: void StateChangeComplete(); sl@0: void CancelChangeState(TInt aReason); //internal request to cancel state change eg due to an error condition sl@0: void Reset(); //utility to reset state to idle and all variables sl@0: sl@0: //MGavdpUser sl@0: virtual void GAVDP_ConnectConfirm(const TBTDevAddr& aDevice); sl@0: virtual void GAVDP_SEPDiscovered(const TAvdtpSEPInfo& aSEP); sl@0: virtual void GAVDP_SEPDiscoveryComplete(); sl@0: virtual void GAVDP_SEPCapability(TAvdtpServiceCapability* aCapability); sl@0: virtual void GAVDP_SEPCapabilityComplete(); sl@0: virtual void GAVDP_AbortStreamConfirm(); sl@0: virtual void GAVDP_StartStreamsConfirm(); sl@0: virtual void GAVDP_SuspendStreamsConfirm(); sl@0: virtual void GAVDP_SecurityControlConfirm(const TDesC8& /*aResponseData*/) {}; sl@0: virtual void GAVDP_ConfigurationConfirm(); sl@0: virtual void GAVDP_ConfigurationStartIndication(TSEID aLocalSEID, TSEID aRemoteSEID); sl@0: virtual TInt GAVDP_ConfigurationIndication(TAvdtpServiceCapability* aCapability); sl@0: virtual TInt GAVDP_ConfigurationEndIndication(); sl@0: virtual TInt GAVDP_StartIndication(TSEID aSEID); sl@0: virtual TInt GAVDP_SuspendIndication(TSEID aSEID); sl@0: virtual TInt GAVDP_SecurityControlIndication(TSEID /*aSEID*/, TDes8& /*aSecurityData*/) {return KErrNotSupported;}; sl@0: virtual void GAVDP_AbortIndication(TSEID aSEID); sl@0: virtual void GAVDP_ReleaseIndication(TSEID aSEID); sl@0: virtual void GAVDP_BearerReady(RSocket aSocket, const TAvdtpSockAddr& aAddress); sl@0: virtual void GAVDP_Error(TInt aError, const TDesC8& aErrorData); sl@0: sl@0: //CActive sl@0: void RunL(); sl@0: void DoCancel(); sl@0: private: sl@0: MGAVDPStateChangeObserver& iGAVDPStateChangeObserver; sl@0: TGAVDPState iInitialState; sl@0: TGAVDPState iCurrentState; sl@0: TGAVDPState iNextState; sl@0: TGAVDPState iTargetState; sl@0: TConfigurationByRemoteHeadsetState iConfigurationByRemoteHeadsetState; sl@0: CA2dpAudioCodecConfiguration& iA2dpCodecSettings; sl@0: TBool iLocalSEPConfigured; sl@0: TBool iChangeOfSelectedHeadsetSEP; sl@0: TBTDevAddr iBTDevAddr; sl@0: TBool iStateChangeInProgress; sl@0: RSocketServ& iSocketServer; sl@0: RSocket iBearerSocket; sl@0: RGavdp iGavdp; sl@0: TSEID iSymbianDeviceSEID; sl@0: TSEID iHeadsetSEID; sl@0: RArray<TSEID> iPotentialSEPs; sl@0: RArray<TUsableSEP> iSymbianDeviceSEPs; sl@0: RArray<TUsableSEP> iUsableSEPs; //SEPs that can actually be used to stream audio sl@0: RPointerArray<TAvdtpServiceCapability> iSEPCapabilities; sl@0: TUint iSEPIterator; //used to iterate through potential SEPs when getting caps sl@0: TUint iSEPCapabilityEntry; sl@0: sl@0: //heap members owned by CGAVDPStateMachine sl@0: CGavdpTimeout* iSignallingTransactionTimeout; sl@0: }; sl@0: sl@0: /** sl@0: The SEP discovery and GetCapabilities do not have built in timeouts, sl@0: so a timeout is required sl@0: sl@0: @internalComponent sl@0: */ sl@0: NONSHARABLE_CLASS(CGavdpTimeout) : public CTimer sl@0: { sl@0: public: sl@0: static CGavdpTimeout* NewL(CGAVDPStateMachine& aGAVDPStateMachine); sl@0: void StartTimer(TTimeIntervalMicroSeconds32 aTimeInterval); sl@0: private: sl@0: CGavdpTimeout(); sl@0: void ConstructL(CGAVDPStateMachine& aGAVDPStateMachine); sl@0: virtual void RunL(); sl@0: private: sl@0: CGAVDPStateMachine* iGAVDPStateMachine; sl@0: }; sl@0: sl@0: sl@0: #endif sl@0: