diff -r 000000000000 -r f63038272f30 bluetoothengine/btsac/src/btsacStateConfiguring.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothengine/btsac/src/btsacStateConfiguring.cpp Mon Jan 18 20:28:57 2010 +0200 @@ -0,0 +1,319 @@ +/* +* Copyright (c) 2002-2005 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: In this state, a stereo audio accessory is configuring us. +* +*/ + + + + +// INCLUDE FILES +#include "btsacStateConfiguring.h" +#include "btsacStateConfigured.h" +#include "btsacStateListening.h" +#include "btsacStateAborting.h" +#include "btsacactive.h" +#include "btsacGavdp.h" +#include "btsacSEPManager.h" +#include "btsacStreamerController.h" +#include "debug.h" + +// A2DP codec-specific element definitions +// in bluetoothAV.h +using namespace SymbianBluetoothAV; + +// Subband codec-specific values +// in bluetoothAV.h +using namespace SymbianSBC; + + +// ================= MEMBER FUNCTIONS ======================= + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::NewL +// ----------------------------------------------------------------------------- +// +CBtsacConfiguring* CBtsacConfiguring::NewL(CBTSAController& aParent, TSEID aLocalSEID, TSEID aRemoteSEID) + { + CBtsacConfiguring* self = new( ELeave ) CBtsacConfiguring(aParent, aLocalSEID, aRemoteSEID); + return self; + } + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::CBtsacConfiguring +// ----------------------------------------------------------------------------- +// +CBtsacConfiguring::CBtsacConfiguring(CBTSAController& aParent, TSEID aLocalSEID, TSEID aRemoteSEID) +: CBtsacState(aParent, EStateConfiguring), iLocalSEID(aLocalSEID), iRemoteSEID(aRemoteSEID), + iSEPFound(EFalse), iRemoteSEPIndex(0), iAudioOpenedBy(EAudioOpenedByNone) + { + } + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::~CBtsacConfiguring +// ----------------------------------------------------------------------------- +// +CBtsacConfiguring::~CBtsacConfiguring() + { + TRACE_FUNC + } + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::EnterL +// ----------------------------------------------------------------------------- +// +void CBtsacConfiguring::EnterL() + { + TRACE_STATE(_L("[BTSAC State] Configuring")) + _LIT(KName, "CBtsacStateConfiguring"); + const TDesC& Name = KName; + Parent().iGavdp->RegisterObserver(this, Name); + + if ( iLocalSEID.SEID() != 1) // we have only one local SEP, SBC + { + TRACE_INFO((_L("CBtsacConfiguring::EnterL() Wrong Local SEP being configured !!!"))) + } + + // we have registered only one local SBC SEP, so aRemoteSEID should be a SBC Audio SEP, + // atleast we assume that. So stash it as SBC Audio SEP + TAvdtpSEPInfo info = TAvdtpSEPInfo(); + info.SetIsSink(ETrue); + info.SetMediaType(EAvdtpMediaTypeAudio); + info.SetSEID(iRemoteSEID); + TRAPD(err, Parent().iRemoteSEPs->NewSEPL(info)); + if (!err) + { + Parent().iRemoteSEPs->SetState(info.SEID(), CBTSACStreamEndPoint::EDiscoveredRemote, &info); + } + else // internal problem + { + CancelActionL(KErrCancel, EGavdpResetReasonGeneral); + } + } + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::CancelActionL +// ----------------------------------------------------------------------------- +// +void CBtsacConfiguring::CancelActionL(TInt aError, TBTSACGavdpResetReason aGavdpReset) + { + TRACE_FUNC + Parent().CompletePendingRequests((KConnectReq | KOpenAudioReq), aError); + Parent().ChangeStateL(CBtsacListening::NewL(Parent(), aGavdpReset, aError)); + } + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::CancelConnectL +// ----------------------------------------------------------------------------- +// +void CBtsacConfiguring::CancelConnectL() + { + TRACE_FUNC + CancelActionL(KErrCancel, EGavdpResetReasonGeneral); // do no cancel till gavdp_error call back recieved + } + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::OpenAudioLinkL +// ----------------------------------------------------------------------------- +// +void CBtsacConfiguring::OpenAudioLinkL(const TBTDevAddr& /*aAddr*/) + { + TRACE_FUNC + // Handle open audio completion later, after configuration is ready (completion will happen + // in CBtsacConfigured state after we receive GAVDP_StartIndication). + } + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::DisconnectL +// ----------------------------------------------------------------------------- +// +void CBtsacConfiguring::DisconnectL() + { + TRACE_FUNC + Parent().CompletePendingRequests(KDisconnectReq, KErrNone); + CancelActionL(KErrCancel, EGavdpResetReasonGeneral); + } + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::GAVDP_BearerReady +// ----------------------------------------------------------------------------- +// +void CBtsacConfiguring::GAVDP_BearerReady(RSocket aNewSocket, const TAvdtpSockAddr& aAddr) + { + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_BearerReady() SEID: %d"), aAddr.SEID().SEID())) + (void) aAddr.SEID(); + Parent().NewAccessory(Parent().GetRemoteAddr()); + + // If there is pending connect request, complete it. + Parent().CompletePendingRequests(KConnectReq, KErrNone); + + // only one socket in this implementation at the moment, + // as we dont have recovery and reporting yet + TRAP_IGNORE(Parent().ChangeStateL(CBtsacConfigured::NewL(Parent(), aNewSocket, iAudioOpenedBy, EStreamConfiguredBySink))); + } + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::GAVDP_ConfigurationIndication +// ----------------------------------------------------------------------------- +// +TInt CBtsacConfiguring::GAVDP_ConfigurationIndication(TAvdtpServiceCapability* aCapability) + { + TRACE_FUNC + Parent().iRemoteSEPs->StoreCaps(iRemoteSEPIndex, aCapability); + if ( aCapability->Category() == EServiceCategoryMediaCodec ) + { + TAvdtpMediaCodecCapabilities& codecCaps = static_cast(*aCapability); + if ( codecCaps.MediaCodecType() == EAudioCodecSBC ) // found SEP that we are interested in + { + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_SEPCapability() Found SBC Audio Sink SEP !!!"))) + iSEPFound = ETrue; + Parent().SetSEPIndex(iRemoteSEPIndex); + } + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::GAVDP_ConfigurationEndIndication +// ----------------------------------------------------------------------------- +// +TInt CBtsacConfiguring::GAVDP_ConfigurationEndIndication() + { + TRACE_FUNC + if ( iSEPFound ) // proposed SEP has SBC (and media transport!) caps + { + RPointerArray SEPCapabilities; + if ((Parent().iRemoteSEPs->GetCaps(Parent().GetSEPIndex(), SEPCapabilities)) ) + { + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() Couldn't retrieve Capabilities !"))) + SEPCapabilities.Close(); + TRAPD(err, CancelActionL(KErrCancel, EGavdpResetReasonGeneral)); + if(err) + { + return KErrNoMemory; + } + return KErrGeneral; + } + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() Retrieve %d capabilities"), SEPCapabilities.Count())) + // loop through all capablities to find sbc codec capablities + TSBCCodecCapabilities SBCCaps; + TAvdtpMediaTransportCapabilities MedTransCaps; + for (TInt index=0; index < SEPCapabilities.Count(); index++) + { + TAvdtpServiceCapability* cap = SEPCapabilities[index]; + TAvdtpServiceCategory cat = cap->Category(); + if ( cat == EServiceCategoryMediaCodec ) + { + SBCCaps = static_cast(*cap); + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() SBC Caps retrieved."))) + } + else if ( cat == EServiceCategoryMediaTransport ) + { + MedTransCaps = static_cast(*cap); + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() Media Transport Caps retrieved."))) + } + } + SEPCapabilities.Close(); + + //Parent().StoreAccInfo(); // stores iRemoteSEPs (SEPManager) into database + + // Check if headset's capabilities suits us + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() Accessory Sampling Frequencies: %d"), SBCCaps.SamplingFrequencies())) + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() Accessory Channel modes: %d"), SBCCaps.ChannelModes())) + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() Accessory Blocks: %d"), SBCCaps.BlockLengths())) + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() Accessory SubBands: %d"), SBCCaps.Subbands())) + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() Accessory Alloc method: %d"), SBCCaps.AllocationMethods())) + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() Accessory Max bitpool: %d"), SBCCaps.MaxBitpoolValue())) + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() Accessory Min bitpool: %d"), SBCCaps.MinBitpoolValue())) + if (Parent().iStreamer->ConfigureSEP(SBCCaps) ) + { + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() Streamer couldn't configure SEP !"))) + TRAPD(err, CancelActionL(KErrCancel, EGavdpResetReasonGeneral)); + if(err) + { + return KErrNoMemory; + } + return KErrGeneral; // capabilites doesn't suit us + } + // Everyting has been done on behalf of us, let's wait GAVDP_BearerReady indication. + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_ConfigurationEndIndication() completed"))) + return KErrNone; + } + else + { + return KErrNotFound; // remote is missing SBC (or media transport!) caps in SEP it proposed + } + } + +// ------------------------------------------------------------- +// CBtsacConfiguring::GAVDP_StartIndication +// ------------------------------------------------------------- +// +TInt CBtsacConfiguring::GAVDP_StartIndication(TSEID aLocalSEID) + { + TRACE_INFO((_L("CBtsacConfiguring::GAVDP_StartIndication(), LocalSEID:%d"), aLocalSEID.SEID())) + (void)aLocalSEID; + + // accessory has send this indication right after GAVDP_ConfigurationEndIndication + // but we must be waiting for Gavdp_BearerReady. In order to solve this, just flag + // our indication that an open audio request exists + // CBtsacConfigured state can use this indication to start audio automatically then later + + // If we have already audio open request pending (from accessory FW), let keep it that way. + // We have to complete open audio request later + if(!Parent().IsOpenAudioReqFromAccFWPending()) + { + iAudioOpenedBy = EAudioOpenedByAcc; + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CBtsacConfiguring::HandleGavdpErrorL +// ----------------------------------------------------------------------------- +// +void CBtsacConfiguring::HandleGavdpErrorL(TInt aError) + { + TRACE_FUNC + switch(aError) + { + case KErrAvdtpRequestTimeout: // -18005 + { + TRACE_INFO((_L("CBtsacConfiguring::HandleGavdpErrorL() Request TIMEOUT"))) + // Go to listening state, gavdp will be shutdown in listening state + CancelActionL(KErrDisconnected, EGavdpResetReasonNone); + break; + } + + case KErrHCILinkDisconnection: // -6305 + case KErrDisconnected: // -36 + { + TRACE_INFO((_L("CBtsacConfiguring::HandleGavdpErrorL() Signalling disconnected."))) + // for both outgoing or incoming connection, if we have an error, + // this means there is disconnection + CancelActionL(aError, EGavdpResetReasonNone); + break; + } + + default: + //case KErrNotReady: // -18 + //case KErrInUse: // -14 + { + CancelActionL(KErrDisconnected, EGavdpResetReasonGeneral); + break; + } + } + } + +// End of File