# HG changeset patch # User Dremov Kirill (Nokia-D-MSW/Tampere) # Date 1274784895 -10800 # Node ID 32ba203390366442e45f2406d00c5c4736628cd1 # Parent 9f17f914e82844cfcfe8ce04b5798a1abea5e528 Revision: 201018 Kit: 2010121 diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/eirman/eirmanager.cpp --- a/bluetooth/btstack/eirman/eirmanager.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/eirman/eirmanager.cpp Tue May 25 13:54:55 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2007-2010 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" @@ -169,7 +169,7 @@ } } -TInt CEirManager::SetData(TEirTag aTag, TDesC8& aData, TEirDataMode aEirDataMode) +TInt CEirManager::SetData(TEirTag aTag, const TDesC8& aData, TEirDataMode aEirDataMode) { LOG_FUNC LOG1(_L("CEirManager::SetData tag = %d"), aTag); diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/eirman/eirmanager.h --- a/bluetooth/btstack/eirman/eirmanager.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/eirman/eirmanager.h Tue May 25 13:54:55 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2007-2010 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" @@ -89,7 +89,7 @@ TInt RegisterTag(TEirTag aTag, MEirManagerNotifiee& aNotifiee); void DeregisterTag(TEirTag aTag); - TInt SetData(TEirTag aTag, TDesC8& aData, TEirDataMode aEirDataMode); + TInt SetData(TEirTag aTag, const TDesC8& aData, TEirDataMode aEirDataMode); // from MHCICommandQueueClient void MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand); diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/eirman/eirmanserver.cpp --- a/bluetooth/btstack/eirman/eirmanserver.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/eirman/eirmanserver.cpp Tue May 25 13:54:55 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2007-2010 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" @@ -58,9 +58,11 @@ : CPolicyServer(CActive::EPriorityStandard, KEirManServerPolicy) , iCommandQueue(aCommandQueue) , iLinkMgrProtocol(aLinkMgrProtocol) - , iSessionCount(0) + , iInternalSessionCount(0) + , iExternalSessionCount(0) , iIsFeaturesReady(EFalse) , iIsEirSupported(EFalse) + , iSessions(_FOFF(CEirManSession, iLink)) { LOG_FUNC } @@ -93,28 +95,63 @@ CEirManServer* ncThis = const_cast(this); - CEirManSession* sess = CEirManSession::NewL(*ncThis); + CEirManExternalSession* sess = CEirManExternalSession::NewL(*ncThis); LOG1(_L("\tsess = 0x%08x"), sess); return sess; } -void CEirManServer::AddSession() +CEirManInternalSession* CEirManServer::NewInternalSessionL(MEirInternalSessionNotifier& aParent) + { + LOG_FUNC + // Server will refuse to create any more session if we have found out eir isn't supported. + if(iIsFeaturesReady && !iIsEirSupported) + { + User::Leave(KErrNotSupported); + } + CEirManInternalSession* sess = CEirManInternalSession::NewL(*this, aParent); + return sess; + } + +void CEirManServer::AddSession(CEirManSession& aSession, TBool aInternalSession) { LOG_FUNC - if(iSessionCount++ == 0) + + iSessions.AddLast(aSession); + + if (aInternalSession) { - // While we have clients we need to make sure that the protocol remains alive. - iLinkMgrProtocol.LocalOpen(); + if(iInternalSessionCount++ == 0) + { + // While we have clients we need to make sure that the protocol remains alive. + iLinkMgrProtocol.LocalOpen(); + } + } + else + { + if(iExternalSessionCount++ == 0) + { + // While we have clients we need to make sure that the protocol remains alive. + iLinkMgrProtocol.Open(); + } } } -void CEirManServer::DropSession() +void CEirManServer::DropSession(TBool aInternalSession) { LOG_FUNC - if(--iSessionCount == 0) + if (aInternalSession) { - // There are no long - iLinkMgrProtocol.LocalClose(); + if(--iInternalSessionCount == 0) + { + iLinkMgrProtocol.LocalClose(); + } + } + else + { + if(--iExternalSessionCount == 0) + { + iLinkMgrProtocol.Close(); + } } } @@ -126,8 +163,10 @@ TRAPD(err, iEirManager = CEirManager::NewL(iCommandQueue, iLinkMgrProtocol)); iIsFeaturesReady = ETrue; - iSessionIter.SetToFirst(); - CSession2* sessionPtr; + TDblQueIter sessionIter(iSessions); + + sessionIter.SetToFirst(); + CEirManSession* sessionPtr; if(iLinkMgrProtocol.IsExtendedInquiryResponseSupportedLocally() && err == KErrNone) { iIsEirSupported = ETrue; @@ -137,10 +176,9 @@ err = ((err != KErrNone) ? KErrNoMemory : KErrNotSupported); } - while((sessionPtr = iSessionIter++) != NULL) + while((sessionPtr = sessionIter++) != NULL) { - CEirManSession* eirSession = static_cast(sessionPtr); - eirSession->NotifyEirFeatureState(err); + sessionPtr->NotifyEirFeatureState(err); } } } diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/eirman/eirmanserver.h --- a/bluetooth/btstack/eirman/eirmanserver.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/eirman/eirmanserver.h Tue May 25 13:54:55 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2007-2010 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" @@ -24,9 +24,11 @@ #include class CEirManSession; +class CEirManInternalSession; class CEirManager; class MHCICommandQueue; class CLinkMgrProtocol; +class MEirInternalSessionNotifier; enum TEirFeatureState { @@ -44,10 +46,12 @@ static CEirManServer* NewL(MHCICommandQueue& aCommandQueue, CLinkMgrProtocol& aLinkMgrProtocol); ~CEirManServer(); + CEirManInternalSession* NewInternalSessionL(MEirInternalSessionNotifier& aParent); + inline CEirManager& EirManager() const; - void AddSession(); - void DropSession(); + void AddSession(CEirManSession& aSession, TBool aInternalSession); + void DropSession(TBool aInternalSession); void NotifyFeaturesReady(); TEirFeatureState EirFeatureState(); @@ -65,9 +69,11 @@ CLinkMgrProtocol& iLinkMgrProtocol; //owned CEirManager* iEirManager; - TInt iSessionCount; + TInt iInternalSessionCount; + TInt iExternalSessionCount; TBool iIsFeaturesReady; TBool iIsEirSupported; + TDblQue iSessions; }; #include "eirmanserver.inl" diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/eirman/eirmansession.cpp --- a/bluetooth/btstack/eirman/eirmansession.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/eirman/eirmansession.cpp Tue May 25 13:54:55 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2007-2010 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" @@ -32,19 +32,21 @@ _LIT8(KLogComponent, LOG_COMPONENT_EIRMANAGER); #endif -CEirManSession* CEirManSession::NewL(CEirManServer& aServer) +CEirManSession* CEirManSession::NewL(CEirManServer& aServer, MEirSessionNotifier& aParent, TBool aInternalSession) { LOG_STATIC_FUNC - CEirManSession* self = new(ELeave) CEirManSession(aServer); + CEirManSession* self = new(ELeave) CEirManSession(aServer, aParent, aInternalSession); CleanupStack::PushL(self); self->ConstructL(); CleanupStack::Pop(self); return self; } -CEirManSession::CEirManSession(CEirManServer& aServer) +CEirManSession::CEirManSession(CEirManServer& aServer, MEirSessionNotifier& aParent, TBool aInternalSession) : iEirManServer(aServer) + , iParent(aParent) , iEirTag(EEirTagRESERVED) + , iInternalSession(aInternalSession) { LOG_FUNC } @@ -52,7 +54,7 @@ void CEirManSession::ConstructL() { LOG_FUNC - iEirManServer.AddSession(); + iEirManServer.AddSession(*this, iInternalSession); } CEirManSession::~CEirManSession() @@ -60,15 +62,154 @@ LOG_FUNC // deregister any registered tag that may be registered DeregisterTag(); + iLink.Deque(); + iEirManServer.DropSession(iInternalSession); + } + +void CEirManSession::RegisterTag(TEirTag aTag) + { + LOG_FUNC + + LOG1(_L("CEirManSession::RegisterTag tag = %d"), aTag); + + if(!(aTag >= EEirTagName && aTag < EEirTagRESERVED)) + { + iParent.MesnRegisterComplete(KErrArgument); + } + else if(iEirTag != EEirTagRESERVED) + { + LOG1(_L("CEirManSession::RegisterTag ERROR, Tag in use: %d"), iEirTag); + iParent.MesnRegisterComplete(KErrInUse); + } + else + { + // Register this tag for callbacks + if(iEirManServer.EirFeatureState() == EEirFeatureReady) + { + // Eir is supported + TInt result = iEirManServer.EirManager().RegisterTag(aTag, *this); + if(result == KErrNone) + { + iEirTag = aTag; + } + iParent.MesnRegisterComplete(result); + } + else if(iEirManServer.EirFeatureState() == EEirFeaturePending) + { + // We don't know if eir is supported or not at this moment + iRegisterPending = ETrue; + iPendingEirTag = aTag; + } + else + { + // Eir is not supported + iParent.MesnRegisterComplete(KErrNotSupported); + } + } + } + +void CEirManSession::DeregisterTag() + { + LOG_FUNC + LOG1(_L("CEirManSession::DeregisterTag tag = %d"), iEirTag); + + if(iEirTag != EEirTagRESERVED) + { + // Deregister this tag for callbacks + iEirManServer.EirManager().DeregisterTag(iEirTag); + iEirTag = EEirTagRESERVED; + } + } + +// Eir Server has tried to register tag +void CEirManSession::NotifyEirFeatureState(TInt aResult) + { + LOG1(_L("Eir Server has been notified feature ready, result: %d"), aResult); + if(aResult == KErrNone && iRegisterPending) + { + __ASSERT_DEBUG(iEirManServer.EirFeatureState() == EEirFeatureReady, EIR_SESSION_PANIC(EEirSessionEirFeatureNotSupported)); + TInt result = iEirManServer.EirManager().RegisterTag(iPendingEirTag, *this); + if(result == KErrNone) + { + iEirTag = iPendingEirTag; + } + iRegisterPending = EFalse; + iParent.MesnRegisterComplete(result); + } + else if(iRegisterPending) + { + iRegisterPending = EFalse; + iParent.MesnRegisterComplete(aResult); + } + } + + +TInt CEirManSession::NewData(TInt aRequiredLength) + { + LOG_FUNC + return iEirManServer.EirManager().NewData(iEirTag, aRequiredLength); + } + + +TInt CEirManSession::SetData(const TDesC8& aData, TEirDataMode aMode) + { + LOG_FUNC + return iEirManServer.EirManager().SetData(iEirTag, aData, aMode); + } + +// Callback from the EIR Manager +void CEirManSession::MemnEirBlockAvailable(TEirTag aTag, TUint aSpaceForTag) + { + LOG_FUNC + LOG2(_L("CEirManSession::MemnEirBlockAvailable Tag: %d space: %d"), aTag, aSpaceForTag); + + // Silently discard callbacks not containing our EIR Tag + if(aTag != iEirTag) + { + __ASSERT_DEBUG(EFalse, EIR_SESSION_PANIC(EEirSessionInvalidEirTag)); + LOG3(_L("CEirManSession::MemnEirBlockAvailable early return: aTag: %d iEirTag: %d space: %d"), aTag, iEirTag, aSpaceForTag); + return; + } + + iParent.MesnSpaceAvailable(aSpaceForTag); + + } + +TEirTag CEirManSession::EirTag() const + { + return iEirTag; + } + +CEirManExternalSession* CEirManExternalSession::NewL(CEirManServer& aServer) + { + CEirManExternalSession* self = new(ELeave) CEirManExternalSession(); + CleanupStack::PushL(self); + self->ConstructL(aServer); + CleanupStack::Pop(self); + return self; + } + +CEirManExternalSession::CEirManExternalSession() + { + + } + +void CEirManExternalSession::ConstructL(CEirManServer& aServer) + { + iSession = CEirManSession::NewL(aServer, *this, EFalse); + } + +CEirManExternalSession::~CEirManExternalSession() + { if(!iDataAvailableListenerMessage.IsNull()) { // complete any outstanding messages. iDataAvailableListenerMessage.Complete(KErrCancel); } - iEirManServer.DropSession(); + delete iSession; } -void CEirManSession::ServiceL(const RMessage2& aMessage) +void CEirManExternalSession::ServiceL(const RMessage2& aMessage) { LOG_FUNC LOG1(_L("CEirManSession::ServiceL aMessage.Function() = %d"), aMessage.Function()); @@ -109,83 +250,28 @@ } } -void CEirManSession::RegisterTag(const RMessage2& aMessage) +void CEirManExternalSession::RegisterTag(const RMessage2& aMessage) { LOG_FUNC - TEirTag tag = static_cast(aMessage.Int0()); LOG1(_L("CEirManSession::RegisterTag tag = %d"), tag); - if(!(tag >= EEirTagName && tag < EEirTagRESERVED)) - { - __ASSERT_ALWAYS(EFalse, aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidTag)); - } - else if(iEirTag != EEirTagRESERVED) - { - LOG1(_L("CEirManSession::RegisterTag ERROR, Tag in use: %d"), iEirTag); - aMessage.Complete(KErrInUse); - } - else - { - // Register this tag for callbacks - if(iEirManServer.EirFeatureState() == EEirFeatureReady) - { - // Eir is supported - TInt result = iEirManServer.EirManager().RegisterTag(tag, *this); - if(result == KErrNone) - { - iEirTag = tag; - } - aMessage.Complete(result); - } - else if(iEirManServer.EirFeatureState() == EEirFeaturePending) - { - // We don't know if eir is supported or not at this moment - iPendingEirTag = tag; - iRegisterMessage = aMessage; - } - else - { - // Eir is not supported - aMessage.Complete(KErrNotSupported); - } - } + iRegisterMessage = aMessage; + + iSession->RegisterTag(tag); + } -void CEirManSession::DeregisterTag() +void CEirManExternalSession::MesnRegisterComplete(TInt aResult) { - LOG_FUNC - LOG1(_L("CEirManSession::DeregisterTag tag = %d"), iEirTag); - - if(iEirTag != EEirTagRESERVED) + if (aResult == KErrArgument) { - // Deregister this tag for callbacks - iEirManServer.EirManager().DeregisterTag(iEirTag); - iEirTag = EEirTagRESERVED; + __ASSERT_ALWAYS(EFalse, iRegisterMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidTag)); } + iRegisterMessage.Complete(aResult); } -// Eir Server has tried to register tag -void CEirManSession::NotifyEirFeatureState(TInt aResult) - { - LOG1(_L("Eir Server has been notified feature ready, result: %d"), aResult); - if(aResult == KErrNone && !iRegisterMessage.IsNull()) - { - __ASSERT_DEBUG(iEirManServer.EirFeatureState() == EEirFeatureReady, EIR_SESSION_PANIC(EEirSessionEirFeatureNotSupported)); - TInt result = iEirManServer.EirManager().RegisterTag(iPendingEirTag, *this); - if(result == KErrNone) - { - iEirTag = iPendingEirTag; - } - iRegisterMessage.Complete(result); - } - else if(!iRegisterMessage.IsNull()) - { - iRegisterMessage.Complete(aResult); - } - } - -TInt CEirManSession::RegisterSpaceAvailableListener(const RMessage2& aMessage, TBool& aComplete) +TInt CEirManExternalSession::RegisterSpaceAvailableListener(const RMessage2& aMessage, TBool& aComplete) { LOG_FUNC @@ -211,16 +297,16 @@ return KErrNone; } -TInt CEirManSession::NewData(const RMessage2& aMessage) +TInt CEirManExternalSession::NewData(const RMessage2& aMessage) { LOG_FUNC - __ASSERT_ALWAYS(iEirTag != EEirTagRESERVED, aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidTag)); + __ASSERT_ALWAYS(iSession->EirTag() != EEirTagRESERVED, aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidTag)); TInt requiredLength = static_cast(aMessage.Int0()); - return iEirManServer.EirManager().NewData(iEirTag, requiredLength); + return iSession->NewData(requiredLength); } -TInt CEirManSession::CancelSpaceAvailableListener() +TInt CEirManExternalSession::CancelSpaceAvailableListener() { LOG_FUNC @@ -234,12 +320,12 @@ return KErrNone; } -TInt CEirManSession::SetData(const RMessage2& aMessage) +TInt CEirManExternalSession::SetData(const RMessage2& aMessage) { LOG_FUNC - __ASSERT_ALWAYS(iEirTag != EEirTagRESERVED, aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidTag)); + __ASSERT_ALWAYS(iSession->EirTag() != EEirTagRESERVED, aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidTag)); TEirDataMode eirDataMode = static_cast(aMessage.Int1()); - LOG2(_L("Tag: %d EirDataMode: %d"), iEirTag, eirDataMode); + LOG1(_L("EirDataMode: %d"), eirDataMode); // No need to allocate memory with an expensive malloc() call (via HBuf8::NewL or whatever), // since the EIR contents fit in the stack, and the EIR Manager will cache the data anyway @@ -248,25 +334,13 @@ if(err == KErrNone) { - err = iEirManServer.EirManager().SetData(iEirTag, data, eirDataMode); + err = iSession->SetData(data, eirDataMode); } return err; } -// Callback from the EIR Manager -void CEirManSession::MemnEirBlockAvailable(TEirTag aTag, TUint aSpaceForTag) +void CEirManExternalSession::MesnSpaceAvailable(TUint aSpaceForTag) { - LOG_FUNC - LOG2(_L("CEirManSession::MemnEirBlockAvailable Tag: %d space: %d"), aTag, aSpaceForTag); - - // Silently discard callbacks not containing our EIR Tag - if(aTag != iEirTag) - { - __ASSERT_DEBUG(EFalse, EIR_SESSION_PANIC(EEirSessionInvalidEirTag)); - LOG3(_L("CEirManSession::MemnEirBlockAvailable early return: aTag: %d iEirTag: %d space: %d"), aTag, iEirTag, aSpaceForTag); - return; - } - if(iDataAvailableListenerMessage.Handle()) { LOG(_L("Listener outstanding, completing request")); @@ -282,14 +356,92 @@ } } -void CEirManSession::CompleteSpaceAvailableRequest(TUint aBytesAvailable) +void CEirManExternalSession::CompleteSpaceAvailableRequest(TUint aBytesAvailable) { LOG_FUNC LOG1(_L("CEirManSession::CompleteSpaceAvailableRequest bytes: %d"), aBytesAvailable); // Offer the space to the client - TPckg pckg(aBytesAvailable); + TPckgC pckg(aBytesAvailable); TInt err = iDataAvailableListenerMessage.Write(0, pckg); iDataAvailableListenerMessage.Complete(err); } +CEirManInternalSession* CEirManInternalSession::NewL(CEirManServer& aServer, MEirInternalSessionNotifier& aParent) + { + LOG_STATIC_FUNC + CEirManInternalSession* self = new(ELeave) CEirManInternalSession(aParent); + CleanupStack::PushL(self); + self->ConstructL(aServer); + CleanupStack::Pop(self); + return self; + } + +CEirManInternalSession::CEirManInternalSession(MEirInternalSessionNotifier& aParent) + : iParent(aParent) + { + + } + +void CEirManInternalSession::ConstructL(CEirManServer& aServer) + { + iSession = CEirManSession::NewL(aServer, *this, ETrue); + iSetDataCb = new (ELeave) CAsyncCallBack(CActive::EPriorityHigh); + TCallBack cb(&SetDataCb, this); + iSetDataCb->Set(cb); + } + +CEirManInternalSession::~CEirManInternalSession() + { + delete iSetDataCb; + delete iSession; + } + +void CEirManInternalSession::RegisterTag(TEirTag aTag) + { + iSession->RegisterTag(aTag); + } + +void CEirManInternalSession::SetData(const TDesC8& aData, TEirDataMode aMode) + { + delete iPendingData; + iPendingData = NULL; + iSetDataCb->Cancel(); + iPendingData = aData.Alloc(); + iPendingMode = aMode; + if (iPendingData) + { + iSetDataCb->CallBack(); + } + } + +TInt CEirManInternalSession::SetDataCb(TAny* aThis) + { + static_cast(aThis)->DoSetData(); + return KErrNone; + } + +void CEirManInternalSession::DoSetData() + { + TInt err = iSession->SetData(*iPendingData, iPendingMode); + if (err != KErrNone) + { + iParent.MeisnSetDataError(err); + } + } + +TInt CEirManInternalSession::NewData(TInt aRequiredLength) + { + return iSession->NewData(aRequiredLength); + } + + +void CEirManInternalSession::MesnRegisterComplete(TInt aResult) + { + iParent.MeisnRegisterComplete(aResult); + } + +void CEirManInternalSession::MesnSpaceAvailable(TUint aSpaceForTag) + { + iParent.MeisnSpaceAvailable(aSpaceForTag - KEirLengthTagLength); + } diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/eirman/eirmansession.h --- a/bluetooth/btstack/eirman/eirmansession.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/eirman/eirmansession.h Tue May 25 13:54:55 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2007-2010 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" @@ -27,41 +27,115 @@ #include "eirmanager.h" class CEirManServer; +class CEirManInternalSession; -NONSHARABLE_CLASS(CEirManSession) : public CSession2, public MEirManagerNotifiee +NONSHARABLE_CLASS(MEirSessionNotifier) + { +public: + virtual void MesnRegisterComplete(TInt aResult) = 0; + virtual void MesnSpaceAvailable(TUint aSpaceForTag) = 0; + }; + +NONSHARABLE_CLASS(MEirInternalSessionNotifier) + { +public: + virtual void MeisnRegisterComplete(TInt aResult) = 0; + virtual void MeisnSpaceAvailable(TUint aSpaceForTag) = 0; + virtual void MeisnSetDataError(TInt aError) = 0; + }; + +NONSHARABLE_CLASS(CEirManSession) : public CBase, public MEirManagerNotifiee { public: - static CEirManSession* NewL(CEirManServer& aServer); + static CEirManSession* NewL(CEirManServer& aServer, MEirSessionNotifier& aParent, TBool aInternalSession); ~CEirManSession(); void NotifyEirFeatureState(TInt aResult); + + void RegisterTag(TEirTag aTag); + TInt SetData(const TDesC8& aData, TEirDataMode aMode); + TInt NewData(TInt aRequiredLength); + TEirTag EirTag() const; + private: - CEirManSession(CEirManServer& aServer); + CEirManSession(CEirManServer& aServer, MEirSessionNotifier& aParent, TBool aInternalSession); void ConstructL(); + void DeregisterTag(); - // ServiceL handlers +private: // from MEirManagerNotifiee + virtual void MemnEirBlockAvailable(TEirTag aTag, TUint aSpaceForTag); + +public: + TDblQueLink iLink; + +private: + CEirManServer& iEirManServer; // unowned + MEirSessionNotifier& iParent; + TEirTag iEirTag; + TEirTag iPendingEirTag; + TBool iRegisterPending; + TBool iInternalSession; + }; + +NONSHARABLE_CLASS(CEirManExternalSession): public CSession2, public MEirSessionNotifier + { +public: + static CEirManExternalSession* NewL(CEirManServer& aServer); + ~CEirManExternalSession(); + +private: + void ConstructL(CEirManServer& aServer); + CEirManExternalSession(); void RegisterTag(const RMessage2& aMessage); TInt RegisterSpaceAvailableListener(const RMessage2& aMessage, TBool& aComplete); TInt CancelSpaceAvailableListener(); + TInt NewData(const RMessage2& aMessage); TInt SetData(const RMessage2& aMessage); - TInt NewData(const RMessage2& aMessage); - + +private: void CompleteSpaceAvailableRequest(TUint aBytesAvailable); - void DeregisterTag(); private: // CSession2 virtuals virtual void ServiceL(const RMessage2& aMessage); -private: // from MEirManagerNotifiee - virtual void MemnEirBlockAvailable(TEirTag aTag, TUint aSpaceForTag); - private: - CEirManServer& iEirManServer; // unowned - TEirTag iEirTag; - TEirTag iPendingEirTag; - TUint iLastSpaceOffered; - TBool iSpaceAvailableListenerOutstanding; + virtual void MesnRegisterComplete(TInt aResult); + virtual void MesnSpaceAvailable(TUint aSpaceForTag); + +private: RMessage2 iRegisterMessage; RMessage2 iDataAvailableListenerMessage; + TUint iLastSpaceOffered; + + CEirManSession* iSession; + }; + +NONSHARABLE_CLASS(CEirManInternalSession) : public CBase, public MEirSessionNotifier + { +public: + static CEirManInternalSession* NewL(CEirManServer& aServer, MEirInternalSessionNotifier& aParent); + ~CEirManInternalSession(); + + void RegisterTag(TEirTag aTag); + void SetData(const TDesC8& aData, TEirDataMode aMode); + TInt NewData(TInt aRequiredLength); + +private: + CEirManInternalSession(MEirInternalSessionNotifier& aParent); + void ConstructL(CEirManServer& aServer); + + static TInt SetDataCb(TAny* aThis); + void DoSetData(); + +private: // from MEirManagerNotifiee + virtual void MesnRegisterComplete(TInt aResult); + virtual void MesnSpaceAvailable(TUint aSpaceForTag); + +private: + CEirManSession* iSession; + MEirInternalSessionNotifier& iParent; + CAsyncCallBack* iSetDataCb; + HBufC8* iPendingData; + TEirDataMode iPendingMode; }; #endif // _EIRMANSESSION_H diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/l2cap/l2capSAPSignalHandler.cpp --- a/bluetooth/btstack/l2cap/l2capSAPSignalHandler.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/l2cap/l2capSAPSignalHandler.cpp Tue May 25 13:54:55 2010 +0300 @@ -631,32 +631,44 @@ // SAP state machine requested that we open the channel before we could do it. // We can do it now. iOpenChannelRequestAwaitingPeerEntityConfig = EFalse; - iSigState->OpenChannelRequest(*this); + iSigState->OpenChannel(*this); } } TBool CL2CapSAPSignalHandler::DelayConfigRequest() { LOG_FUNC - iAwaitingConfigRequestDelayTimer = iSAPSignalHandlerTimerState==EConfigRequestDelayTimer; + // The whole delaying of sending of ConfigRequest is basically a workaround for + // certain broken carkits from a certain Swedish manufacturer at a certain stretch + // of time. + // The defect was: the carkits advertised their capability to do RTM in Extended + // Feature Mask, but when sent a ConfigRequest with RTM they would just panic + // (ie. they really only did Basic mode). + // So the workaround is to delay the sending of our Config Request such that + // we receive the carkit's request first - we have an optimization which will + // downgrade our requested channel mode to Basic if the remote requests it before + // we've sent out our ConfigReq. This way we send Basic mode in our ConfigReq + // and the carkit is happy. + return iSAPSignalHandlerTimerState==EConfigRequestDelayTimer; + } - return iAwaitingConfigRequestDelayTimer; //true if we are delaying - } - void CL2CapSAPSignalHandler::ConfigRequestDelayTimerExpiry() { LOG_FUNC - if(iAwaitingConfigRequestDelayTimer) + // Now that ConfigReq delay timer have expired we can start the proper configuration timer. + StartConfigurationTimer(); + + if (!iAwaitConfigureChannelRequest) { - iAwaitingConfigRequestDelayTimer = EFalse; - ConfigureChannelRequest(); + ConfigureChannel(); } + // [else]: we're in an active open scenario and SAP hasn't yet issued a ConfigureChannelRequest. } void CL2CapSAPSignalHandler::CloseChannelRequest() { LOG_FUNC - iSigState->CloseChannelRequest(*this); + iSigState->CloseChannel(*this); } void CL2CapSAPSignalHandler::OpenChannelRequest() @@ -667,7 +679,7 @@ if (IsPeerInfoDefined()) { - iSigState->OpenChannelRequest(*this); + iSigState->OpenChannel(*this); } else { @@ -686,7 +698,12 @@ void CL2CapSAPSignalHandler::ConfigureChannelRequest() { LOG_FUNC - iSigState->ConfigureChannelRequest(*this); + iAwaitConfigureChannelRequest = EFalse; + + if (iSAPSignalHandlerTimerState != EConfigRequestDelayTimer) + { + ConfigureChannel(); + } } void CL2CapSAPSignalHandler::PendingCommandsDrained() @@ -707,34 +724,31 @@ void CL2CapSAPSignalHandler::StartConfigurationTimer() { LOG_FUNC - switch(iSAPSignalHandlerTimerState) - { - case EConfigurationTimer: - case EConfigRequestDelayTimer: - // The timer is already running. Cancel it and start it again. - BTSocketTimer::Remove(iSAPSignalHandlerTimerEntry); - iSAPSignalHandlerTimerState = ETimerIdle; - break; - - case ETimerIdle: - default: - // No timer running, nothing needs to be done. - break; - }; + __ASSERT_DEBUG(iSAPSignalHandlerTimerState == ETimerIdle, + Panic(EL2CapAttemptToStartConfigTimerWhenItIsRunning)); + + TCallBack cb(TimerExpired, this); + iSAPSignalHandlerTimerEntry.Set(cb); + BTSocketTimer::Queue(KL2ConfigWatchdogTimeout * KL2ProtocolSecondTimerMultiplier, + iSAPSignalHandlerTimerEntry); + iSAPSignalHandlerTimerState = EConfigurationTimer; + } - if(iSAPSignalHandlerTimerState == ETimerIdle) - { - TCallBack cb(TimerExpired, this); - iSAPSignalHandlerTimerEntry.Set(cb); - BTSocketTimer::Queue(KL2ConfigRequestDelayTimout, - iSAPSignalHandlerTimerEntry); - iSAPSignalHandlerTimerState = EConfigRequestDelayTimer; - } +void CL2CapSAPSignalHandler::StartConfigRequestDelayTimer() + { + LOG_FUNC + __ASSERT_DEBUG(iSAPSignalHandlerTimerState == ETimerIdle, + Panic(EL2CapAttemptToStartConfigTimerWhenItIsRunning)); + + TCallBack cb(TimerExpired, this); + iSAPSignalHandlerTimerEntry.Set(cb); + BTSocketTimer::Queue(KL2ConfigRequestDelayTimout, + iSAPSignalHandlerTimerEntry); + iSAPSignalHandlerTimerState = EConfigRequestDelayTimer; } - + void CL2CapSAPSignalHandler::CancelTimer() { - LOG_FUNC if(iSAPSignalHandlerTimerState != ETimerIdle) { @@ -751,18 +765,14 @@ case ETimerIdle: Panic(EL2CAPSSHTimerExpiredWhileInIdleState); break; - + case EConfigRequestDelayTimer: { - TCallBack cb(TimerExpired, this); - iSAPSignalHandlerTimerEntry.Set(cb); - BTSocketTimer::Queue(KL2ConfigWatchdogTimeout * KL2ProtocolSecondTimerMultiplier, - iSAPSignalHandlerTimerEntry); - iSAPSignalHandlerTimerState = EConfigurationTimer; + iSAPSignalHandlerTimerState = ETimerIdle; ConfigRequestDelayTimerExpiry(); } break; - + case EConfigurationTimer: iSAPSignalHandlerTimerState = ETimerIdle; iSigState->ConfigurationTimerExpiry(*this); diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/l2cap/l2capSAPSignalHandler.h --- a/bluetooth/btstack/l2cap/l2capSAPSignalHandler.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/l2cap/l2capSAPSignalHandler.h Tue May 25 13:54:55 2010 +0300 @@ -128,6 +128,7 @@ static TInt TimerExpired(TAny* aSAPSignalHandler); void StartConfigurationTimer(); + void StartConfigRequestDelayTimer(); void CancelTimer(); void DetachFromMux(); @@ -136,14 +137,16 @@ TInt SendEchoRequest(const TDes8* aData); void EchoResponseReceived(const TDesC8* aData); + inline void ConfigureChannel(); + void OverrideParkMode(); void UndoOverrideParkMode(); void OverrideLPMWithTimeout(); + inline TInt SignalHandlerErrorCode() const; inline MSocketNotify::TOperationBitmasks SignalHandlerErrorAction() const; inline void SetSignalHandlerErrorCode(TInt aError); inline void SetSignalHandlerErrorAction(MSocketNotify::TOperationBitmasks aAction); - private: CL2CapSAPSignalHandler(CL2CAPConnectionSAP& aSAP); void ConstructL(); @@ -187,9 +190,14 @@ // OpenChannelRequest, so OpenChannelRequest is delayed until Information Response comes // through. TBool iOpenChannelRequestAwaitingPeerEntityConfig; - // The SAP is ready to send a config request - // Flag to indicate that we are delaying sending this config request - TBool iAwaitingConfigRequestDelayTimer; + // A ConfigureChannelRequest from the SAP is only expected in an active open scenario. + // On passive open we kick the configuration ourselves. + TBool iAwaitConfigureChannelRequest; + + friend class TL2CAPSigStateClosed; + friend class TL2CAPSigStateWaitConnectRsp; + friend class TL2CAPSigStateWaitConnect; + friend class TL2CAPSigStateConfigBase; }; inline TUint8 CL2CapSAPSignalHandler::GetOutstandingRequestID() @@ -230,7 +238,7 @@ { return iRemotePort; } - + inline const TBTDevAddr& CL2CapSAPSignalHandler::RemoteBTAddress() const { return iSAP->RemoteDev(); @@ -280,5 +288,10 @@ { iSignalHandlerErrorAction = aAction; } - + +inline void CL2CapSAPSignalHandler::ConfigureChannel() + { + iSigState->ConfigureChannel(*this); + } + #endif diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/l2cap/l2capSigStates.cpp --- a/bluetooth/btstack/l2cap/l2capSigStates.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/l2cap/l2capSigStates.cpp Tue May 25 13:54:55 2010 +0300 @@ -49,7 +49,7 @@ } // Events from the SAP -void TL2CAPSigState::CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const +void TL2CAPSigState::CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC // This is a standard action for most states. @@ -62,7 +62,7 @@ aSignalHandler.SAP()->ChannelClosed(); } -void TL2CAPSigState::OpenChannelRequest(CL2CapSAPSignalHandler& /*aSignalHandler*/) const +void TL2CAPSigState::OpenChannel(CL2CapSAPSignalHandler& /*aSignalHandler*/) const { LOG_FUNC PanicInState(EL2CAPUnexpectedSAPEvent); @@ -74,7 +74,7 @@ PanicInState(EL2CAPUnexpectedSAPEvent); } -void TL2CAPSigState::ConfigureChannelRequest(CL2CapSAPSignalHandler& /*aSignalHandler*/) const +void TL2CAPSigState::ConfigureChannel(CL2CapSAPSignalHandler& /*aSignalHandler*/) const { LOG_FUNC PanicInState(EL2CAPUnexpectedSAPEvent); @@ -282,7 +282,7 @@ LOG_FUNC } -void TL2CAPSigStateClosed::OpenChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const +void TL2CAPSigStateClosed::OpenChannel(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC // The SAP has requested a channel be opened. @@ -353,7 +353,7 @@ } -void TL2CAPSigStateClosed::CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const +void TL2CAPSigStateClosed::CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC // Detach from the Mux. Inform the SAP that disconnection is complete. @@ -382,6 +382,8 @@ // Cancel the configuration timer. aSignalHandler.CancelTimer(); + aSignalHandler.iOpenChannelRequestAwaitingPeerEntityConfig = EFalse; + // If Park mode has been overridden during either channel establishment or // channel disconnect, remove the override. // NB It is safe to call this method multiple times. @@ -446,7 +448,7 @@ } // Events from the Mux -void TL2CAPSigStateWaitConnectRsp::CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const +void TL2CAPSigStateWaitConnectRsp::CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const { // Disconnect the channel. HandleSAPDisconnect(aSignalHandler); @@ -457,6 +459,7 @@ LOG_FUNC //set the remote CID to 0 aSignalHandler.SetRemotePort(TL2CAPPort(0)); + aSignalHandler.iAwaitConfigureChannelRequest = ETrue; } /****************************************************************************/ @@ -469,7 +472,7 @@ } // Events from the SAP -void TL2CAPSigStateWaitConnect::OpenChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const +void TL2CAPSigStateWaitConnect::OpenChannel(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC @@ -489,7 +492,7 @@ // We should never get in here! The timer, which allows the delay // should have been started on entry to the state "WaitConfig". { - aSignalHandler.ConfigureChannelRequest(); + aSignalHandler.ConfigureChannel(); } } } // Success Response @@ -516,7 +519,7 @@ } // Events from the Mux -void TL2CAPSigStateWaitConnect::CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const +void TL2CAPSigStateWaitConnect::CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC @@ -567,6 +570,12 @@ HandleDisconnectRequest(aSignalHandler, aId); } +void TL2CAPSigStateWaitConnect::Enter(CL2CapSAPSignalHandler& aSignalHandler) const + { + LOG_FUNC + aSignalHandler.iAwaitConfigureChannelRequest = EFalse; + } + /**************************************************************************/ // Implementation of TL2CAPSigStateConfigBase @@ -606,7 +615,7 @@ } // Events from the SAP -void TL2CAPSigStateConfigBase::CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const +void TL2CAPSigStateConfigBase::CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC // Disconnect the channel. @@ -624,7 +633,7 @@ void TL2CAPSigStateConfigBase::ConfigurationTimerExpiry(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC - CloseChannelRequest(aSignalHandler); + CloseChannel(aSignalHandler); } // Common handling of Config Request and Response commands. @@ -669,13 +678,29 @@ case EConfigSuccess: // Move to next state. aSignalHandler.SetState(iFactory.GetState(aConfigSuccessState)); + + if (!configRequestSent && !aSignalHandler.iAwaitConfigureChannelRequest) + { + // The delay timer is there so that we don't send a + // Config Req before receiving one from the remote + // (as a workaround for some broken carkits, see + // DelayConfigRequest()). Since we've just received a + // ConfigReq from the remote, we can stop the delay + // timer and send our request if this is passive open + // or remotely-initiated reconfiguration. + // If it's an active open scenario then we need to wait + // for security access request to get completed. + aSignalHandler.CancelTimer(); + aSignalHandler.StartConfigurationTimer(); + aSignalHandler.ConfigureChannel(); + } break; - + case EConfigUnacceptableParams: case EConfigRejected: // Stay in current state. break; - + case EConfigUnknownOption: // impossible on this path default: __ASSERT_DEBUG(EFalse, PanicInState(EL2CAPInvalidConfigResponseCodeGenerated)); @@ -836,7 +861,7 @@ } // Events from the SAP -void TL2CAPSigStateWaitConfig::ConfigureChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const +void TL2CAPSigStateWaitConfig::ConfigureChannel(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC // Local config can now be initiated. The local config requirements must @@ -851,7 +876,7 @@ if(err == KErrNone) { aSignalHandler.SetState(iFactory.GetState(CL2CAPSignalStateFactory::EWaitConfigReqRsp)); - } + } else { Error(aSignalHandler, KErrCouldNotConnect, MSocketNotify::EErrorAllOperations); @@ -859,7 +884,7 @@ } // Else wait until the delay timer expires. } - + // L2CAP commands received from the peer. void TL2CAPSigStateWaitConfig::ConfigRequest(CL2CapSAPSignalHandler& aSignalHandler, HConfigureRequest* aConfigRequest) const @@ -868,12 +893,14 @@ // Call the config base class helper method to process this command. TL2CAPSigStateConfigBase::ConfigRequest(aSignalHandler, aConfigRequest, CL2CAPSignalStateFactory::EWaitSendConfig); } - + // Change of state events void TL2CAPSigStateWaitConfig::Enter(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC - aSignalHandler.StartConfigurationTimer(); + // First start the ConfigReq sending delay timer (see DelayConfigRequest() for why). + // It's short lived, we'll start the proper L2CAP config timer when it expires. + aSignalHandler.StartConfigRequestDelayTimer(); } /**************************************************************************/ @@ -890,7 +917,7 @@ } // Events from the SAP -void TL2CAPSigStateWaitSendConfig::ConfigureChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const +void TL2CAPSigStateWaitSendConfig::ConfigureChannel(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC // Local config can now be initiated. The local config requirements must @@ -1005,9 +1032,6 @@ // should not be sent until it completes. aSignalHandler.ReconfiguringChannel(); static_cast(aSignalHandler.HandleConfigureRequest(aConfigRequest)); - - // Start local reconfiguration. - aSignalHandler.ConfigureChannelRequest(); } TInt TL2CAPSigStateOpen::UpdateChannelConfig(CL2CapSAPSignalHandler& aSignalHandler, const TL2CapConfig& aAPIConfig) const @@ -1019,14 +1043,14 @@ { aSignalHandler.ReconfiguringChannel(); aSignalHandler.SetState(iFactory.GetState(CL2CAPSignalStateFactory::EWaitConfig)); - aSignalHandler.ConfigureChannelRequest(); + aSignalHandler.ConfigureChannel(); rerr = KErrL2CAPConfigPending; } return rerr; } -void TL2CAPSigStateOpen::CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const +void TL2CAPSigStateOpen::CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC // Disconnect the channel. @@ -1060,16 +1084,16 @@ LOG(_L("CL2CapSigStateOpen::Enter doing reconfig")); // now get reconfiguring aSignalHandler.SetState(iFactory.GetState(CL2CAPSignalStateFactory::EWaitConfig)); - aSignalHandler.ConfigureChannelRequest(); + aSignalHandler.ConfigureChannel(); } else { // Remove and park override. aSignalHandler.UndoOverrideParkMode(); - + // Cancel the configuration timer. aSignalHandler.CancelTimer(); - + // Inform the SAP that the channel is now configured and ready to use. aSignalHandler.SAP()->ChannelConfigured(aSignalHandler.ChannelConfig(), aSignalHandler.Mux(), @@ -1153,7 +1177,7 @@ aSignalHandler.CancelTimer(); } -void TL2CAPSigStateWaitDisconnect::CloseChannelRequest(CL2CapSAPSignalHandler& /*aSignalHandler*/) const +void TL2CAPSigStateWaitDisconnect::CloseChannel(CL2CapSAPSignalHandler& /*aSignalHandler*/) const { LOG_FUNC // Already disconnecting. @@ -1201,7 +1225,7 @@ // Could well be in this state - just drop. } -void TL2CAPSigStateWaitDisconnect::ConfigureChannelRequest(CL2CapSAPSignalHandler& /*aSignalHandler*/) const +void TL2CAPSigStateWaitDisconnect::ConfigureChannel(CL2CapSAPSignalHandler& /*aSignalHandler*/) const { LOG_FUNC // This may be called if an Information Request times out diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/l2cap/l2capSigStates.h --- a/bluetooth/btstack/l2cap/l2capSigStates.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/l2cap/l2capSigStates.h Tue May 25 13:54:55 2010 +0300 @@ -78,10 +78,10 @@ TL2CAPSigState(const CL2CAPSignalStateFactory& aFactory); // Events from the SAP - virtual void CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; - virtual void OpenChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; + virtual void CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const; + virtual void OpenChannel(CL2CapSAPSignalHandler& aSignalHandler) const; virtual void ConnectRequestReceived(CL2CapSAPSignalHandler& aSignalHandler) const; - virtual void ConfigureChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; + virtual void ConfigureChannel(CL2CapSAPSignalHandler& aSignalHandler) const; virtual TInt UpdateChannelConfig(CL2CapSAPSignalHandler& aSignalHandler, const TL2CapConfig& aAPIConfig) const; virtual TInt GetNegotiatedChannelMode(const CL2CapSAPSignalHandler& aSignalHandler, TL2CapChannelMode& aMode) const; @@ -142,9 +142,9 @@ TL2CAPSigStateClosed(const CL2CAPSignalStateFactory& aFactory); // Events from the SAP - void OpenChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; + void OpenChannel(CL2CapSAPSignalHandler& aSignalHandler) const; void ConnectRequestReceived(CL2CapSAPSignalHandler& aSignalHandler) const; - void CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; + void CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const; void ConfigRequest(CL2CapSAPSignalHandler& aSignalHandler, HConfigureRequest* aConfigRequest) const; @@ -165,7 +165,7 @@ TL2CAPSigStateWaitConnectRsp(const CL2CAPSignalStateFactory& aFactory); // Events from the SAP - void CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; + void CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const; // L2CAP commands received from the peer. void ConnectResponse(CL2CapSAPSignalHandler& aSignalHandler, @@ -183,15 +183,16 @@ TL2CAPSigStateWaitConnect(const CL2CAPSignalStateFactory& aFactory); // Events from the SAP - void OpenChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; - void CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; + void OpenChannel(CL2CapSAPSignalHandler& aSignalHandler) const; + void CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const; // L2CAP commands received from the peer. void DisconnectRequest(CL2CapSAPSignalHandler& aSignalHandler, TUint8 aId) const; // Change of state state events void PendingCommandsDrained(CL2CapSAPSignalHandler& aSignalHandler) const; - + + void Enter(CL2CapSAPSignalHandler& aSignalHandler) const; }; NONSHARABLE_CLASS(TL2CAPSigStateConfigBase) : public TL2CAPSigState @@ -212,7 +213,7 @@ MSocketNotify::TOperationBitmasks aErrorAction) const; // Events from the SAP - void CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; + void CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const; TInt UpdateChannelConfig(CL2CapSAPSignalHandler& aSignalHandler, const TL2CapConfig& aAPIConfig) const; // Timer Events @@ -238,7 +239,7 @@ TL2CAPSigStateWaitConfig(const CL2CAPSignalStateFactory& aFactory); // Events from the SAP - void ConfigureChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; + void ConfigureChannel(CL2CapSAPSignalHandler& aSignalHandler) const; // L2CAP commands received from the peer. void ConfigRequest(CL2CapSAPSignalHandler& aSignalHandler, @@ -259,7 +260,7 @@ TL2CAPSigStateWaitSendConfig(const CL2CAPSignalStateFactory& aFactory); // Events from the SAP - void ConfigureChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; + void ConfigureChannel(CL2CapSAPSignalHandler& aSignalHandler) const; }; NONSHARABLE_CLASS(TL2CAPSigStateWaitConfigReqRsp) : public TL2CAPSigStateConfigBase @@ -317,7 +318,7 @@ TL2CAPSigStateOpen(const CL2CAPSignalStateFactory& aFactory); // Events from the SAP - void CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; + void CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const; // L2CAP commands received from the peer. void DisconnectRequest(CL2CapSAPSignalHandler& aSignalHandler, TUint8 aId) const; @@ -343,7 +344,7 @@ TL2CAPSigStateWaitDisconnect(const CL2CAPSignalStateFactory& aFactory); // Events from the SAP - void CloseChannelRequest(CL2CapSAPSignalHandler& aSignalHandler) const; + void CloseChannel(CL2CapSAPSignalHandler& aSignalHandler) const; TInt UpdateChannelConfig(CL2CapSAPSignalHandler& aSignalHandler, const TL2CapConfig& aAPIConfig) const; // State changes from the Mux @@ -360,7 +361,7 @@ void ConfigResponse(CL2CapSAPSignalHandler& /*aSignalHandler*/, HConfigureResponse* /*aConfigResponse*/) const; - void ConfigureChannelRequest(CL2CapSAPSignalHandler& /*aSignalHandler*/) const; + void ConfigureChannel(CL2CapSAPSignalHandler& /*aSignalHandler*/) const; }; #endif diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/l2cap/l2util.h --- a/bluetooth/btstack/l2cap/l2util.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/l2cap/l2util.h Tue May 25 13:54:55 2010 +0300 @@ -172,7 +172,8 @@ EL2CAPNullOwnerSupplied = 148, EL2CAPTryingToStealOwnedPdu = 149, EL2CapConstructingPositiveConfigResponseWithUnresolvedOptionStatus = 200, - EL2CapReferencingUnackedIFrameWhenNoRetransmissionGoing = 274, + EL2CapReferencingUnackedIFrameWhenNoRetransmissionGoing = 274, + EL2CapAttemptToStartConfigTimerWhenItIsRunning = 275, }; /** diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/linkmgr/ACLSAP.cpp --- a/bluetooth/btstack/linkmgr/ACLSAP.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/linkmgr/ACLSAP.cpp Tue May 25 13:54:55 2010 +0300 @@ -1089,13 +1089,7 @@ CPhysicalLink* physicalLink = &iLinksMan.NewPhysicalLinkL(iRemoteDev); // physicalLink is owned by the physical links manager. User::LeaveIfError(BindLink(EACLLink, *physicalLink)); - TInt err = iPhysicalLink->Connect(); - if(err != KErrNone) - { - // If we failed to connect then we should roll back the attachment - ClearPhysicalLink(); - User::Leave(err); - } + iPhysicalLink->Connect(); } } diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/linkmgr/ProxySAP.cpp --- a/bluetooth/btstack/linkmgr/ProxySAP.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/linkmgr/ProxySAP.cpp Tue May 25 13:54:55 2010 +0300 @@ -552,7 +552,7 @@ } else { - iRequestedActiveMode = option ? ETrue : EFalse; + iRequestedActiveMode = option; if(iRequestedActiveMode) { localPriority = ETrue; diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/linkmgr/ProxySAP.h --- a/bluetooth/btstack/linkmgr/ProxySAP.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/linkmgr/ProxySAP.h Tue May 25 13:54:55 2010 +0300 @@ -80,6 +80,7 @@ public: static CBTProxySAP* NewLC(CPhysicalLinksManager& aConnectionMan, CPhysicalLink*); static CBTProxySAP* NewL(CPhysicalLinksManager& aConnectionMan, CPhysicalLink*); + ~CBTProxySAP(); // from SAP - the proxy will not do all of these virtual void Start(); @@ -122,8 +123,7 @@ void Error(TInt aError); void Disconnect(); - - ~CBTProxySAP(); + public: TSglQueLink iQueueLink; TBTDblQueLink iPLMLink; diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/linkmgr/eirpublisherlocalname.cpp --- a/bluetooth/btstack/linkmgr/eirpublisherlocalname.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/linkmgr/eirpublisherlocalname.cpp Tue May 25 13:54:55 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2008-2010 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" @@ -15,9 +15,10 @@ #include "eirpublisherlocalname.h" #include "linkutil.h" -#include #include +#include "eirmanserver.h" + #ifdef __FLOG_ACTIVE _LIT8(KLogComponent, LOG_COMPONENT_EIRMANAGER); #endif @@ -29,18 +30,17 @@ /** Provides functionality to publish Local Name to EIR. **/ -CEirPublisherLocalName* CEirPublisherLocalName::NewL() +CEirPublisherLocalName* CEirPublisherLocalName::NewL(CEirManServer& aServer) { LOG_STATIC_FUNC CEirPublisherLocalName* self = new (ELeave) CEirPublisherLocalName(); CleanupStack::PushL(self); - self->ConstructL(); + self->ConstructL(aServer); CleanupStack::Pop(); return self; } CEirPublisherLocalName::CEirPublisherLocalName() -: CEirPublisherBase(EEirTagName) { LOG_FUNC } @@ -49,26 +49,49 @@ { LOG_FUNC delete iPublishBuf; + delete iSession; } -void CEirPublisherLocalName::ConstructL() +void CEirPublisherLocalName::ConstructL(CEirManServer& aServer) { LOG_FUNC - CEirPublisherBase::ConstructL(); + iSession = aServer.NewInternalSessionL(*this); + iSession->RegisterTag(EEirTagName); } + +void CEirPublisherLocalName::MeisnRegisterComplete(TInt aResult) + { + if (aResult == KErrNone) + { + iTagRegistered = ETrue; + if (iLocalName.Length() > 0) + { + iSession->NewData(iLocalName.Length()); + } + } + } + +void CEirPublisherLocalName::MeisnSetDataError(TInt /* aError */) + { + } + + void CEirPublisherLocalName::UpdateName(const TDesC8& aName) { LOG_FUNC // Check aName isn't longer than 248 characters __ASSERT_DEBUG(aName.Length() <= 248, Panic(EEIRPublisherUpdateNameTooLong)); iLocalName = aName; - iPublisher->PublishData(aName.Size()); + if (iTagRegistered) + { + iSession->NewData(iLocalName.Size()); + } } // From MEirPublisherNotifier -void CEirPublisherLocalName::MepnSpaceAvailable(TUint aBytesAvailable) +void CEirPublisherLocalName::MeisnSpaceAvailable(TUint aBytesAvailable) { LOG_FUNC // Delete memory from last time this was called @@ -84,7 +107,7 @@ iPublishBuf = iLocalName.Left(avail).Alloc(); if(iPublishBuf) { - iPublisher->SetData(*iPublishBuf, EEirDataPartial); + iSession->SetData(*iPublishBuf, EEirDataPartial); } } else @@ -94,17 +117,14 @@ iPublishBuf = iLocalName.Alloc(); if(iPublishBuf) { - iPublisher->SetData(*iPublishBuf, EEirDataComplete); + iSession->SetData(*iPublishBuf, EEirDataComplete); } } // Final case to handle if OOM occurs. if(!iPublishBuf) { - iPublisher->SetData(KNullDesC8(), EEirDataPartial); + iSession->SetData(KNullDesC8(), EEirDataPartial); } } - -void CEirPublisherLocalName::MepnSetDataError(TInt /*aResult*/) - { - LOG_FUNC - } + + diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/linkmgr/eirpublisherlocalname.h --- a/bluetooth/btstack/linkmgr/eirpublisherlocalname.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/linkmgr/eirpublisherlocalname.h Tue May 25 13:54:55 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2008-2010 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" @@ -17,8 +17,10 @@ #define EIRPUBLISHERLOCALNAME_H #include -#include #include +#include "eirmansession.h" + +class CEirManServer; //********************************** // CEirPublisherLocalName @@ -26,24 +28,27 @@ /** Provides functionality to publish 16 bit UUIDs to EIR. **/ -NONSHARABLE_CLASS(CEirPublisherLocalName) : public CEirPublisherBase +NONSHARABLE_CLASS(CEirPublisherLocalName): public CBase, public MEirInternalSessionNotifier { public: - static CEirPublisherLocalName* NewL(); + static CEirPublisherLocalName* NewL(CEirManServer& aServer); ~CEirPublisherLocalName(); void UpdateName(const TDesC8& aName); private: CEirPublisherLocalName(); - void ConstructL(); + void ConstructL(CEirManServer& aServer); - // From MEirPublisherNotifier - virtual void MepnSpaceAvailable(TUint aBytesAvailable); - virtual void MepnSetDataError(TInt aResult); + // From MEirInternalSessionNotifier + virtual void MeisnSpaceAvailable(TUint aBytesAvailable); + virtual void MeisnRegisterComplete(TInt aResult); + virtual void MeisnSetDataError(TInt aError); private: TBuf8 iLocalName; HBufC8* iPublishBuf; + CEirManInternalSession* iSession; + TBool iTagRegistered; }; #endif // EIRPUBLISHERLOCALNAME_H diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/linkmgr/eirpublishertxpowerlevel.cpp --- a/bluetooth/btstack/linkmgr/eirpublishertxpowerlevel.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/linkmgr/eirpublishertxpowerlevel.cpp Tue May 25 13:54:55 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2008-2010 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" @@ -14,7 +14,7 @@ // #include "eirpublishertxpowerlevel.h" -#include +#include "eirmanserver.h" //********************************** // CEirPublisherTxPowerLevel @@ -22,53 +22,71 @@ /** Provides functionality to publish transmission power level to EIR. **/ -CEirPublisherTxPowerLevel* CEirPublisherTxPowerLevel::NewL() +CEirPublisherTxPowerLevel* CEirPublisherTxPowerLevel::NewL(CEirManServer& aServer) { CEirPublisherTxPowerLevel* self = new (ELeave) CEirPublisherTxPowerLevel(); CleanupStack::PushL(self); - self->ConstructL(); + self->ConstructL(aServer); CleanupStack::Pop(); return self; } CEirPublisherTxPowerLevel::CEirPublisherTxPowerLevel() -: CEirPublisherBase(EEirTagTxPowerLevel) { } -void CEirPublisherTxPowerLevel::ConstructL() +void CEirPublisherTxPowerLevel::ConstructL(CEirManServer& aServer) { - CEirPublisherBase::ConstructL(); + iSession = aServer.NewInternalSessionL(*this); + iSession->RegisterTag(EEirTagTxPowerLevel); } CEirPublisherTxPowerLevel::~CEirPublisherTxPowerLevel() { + delete iSession; + } + +void CEirPublisherTxPowerLevel::MeisnRegisterComplete(TInt aResult) + { + if (aResult == KErrNone) + { + iTagRegistered = ETrue; + if (iTxPowerLevelPublished) + { + iSession->NewData(KSizeOfTxPowerLevelData); + } + } } void CEirPublisherTxPowerLevel::UpdateTxPowerLevel(TInt8 aTxPowerLevel) { iTxPowerLevel = aTxPowerLevel; - iPublisher->PublishData(KSizeOfTxPowerLevelData); + iTxPowerLevelPublished = ETrue; + if (iTagRegistered) + { + iSession->NewData(KSizeOfTxPowerLevelData); + } } // From MEirPublisherNotifier -void CEirPublisherTxPowerLevel::MepnSpaceAvailable(TUint aBytesAvailable) +void CEirPublisherTxPowerLevel::MeisnSpaceAvailable(TUint aBytesAvailable) { if (aBytesAvailable >= KSizeOfTxPowerLevelData) { // only publish TxPowerLevel if enough space iPublishBuf.Zero(); iPublishBuf.Append(iTxPowerLevel); - iPublisher->SetData(iPublishBuf, EEirDataComplete); + iSession->SetData(iPublishBuf, EEirDataComplete); } else { // Otherwise publish zero length string iPublishBuf.Zero(); - iPublisher->SetData(iPublishBuf, EEirDataPartial); + iSession->SetData(iPublishBuf, EEirDataPartial); } } -void CEirPublisherTxPowerLevel::MepnSetDataError(TInt /*aResult*/) +void CEirPublisherTxPowerLevel::MeisnSetDataError(TInt /* aError */) { + } diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/linkmgr/eirpublishertxpowerlevel.h --- a/bluetooth/btstack/linkmgr/eirpublishertxpowerlevel.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/linkmgr/eirpublishertxpowerlevel.h Tue May 25 13:54:55 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2008-2010 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" @@ -18,7 +18,9 @@ #define EIRPUBLISHERTXPOWERLEVEL_H #include -#include +#include "eirmansession.h" + +class CEirManServer; #define KSizeOfTxPowerLevelData 1 @@ -28,24 +30,28 @@ /** Provides functionality to publish TxPowerLevel to EIR. **/ -NONSHARABLE_CLASS(CEirPublisherTxPowerLevel) : public CEirPublisherBase +NONSHARABLE_CLASS(CEirPublisherTxPowerLevel) : public CBase, public MEirInternalSessionNotifier { public: - static CEirPublisherTxPowerLevel* NewL(); + static CEirPublisherTxPowerLevel* NewL(CEirManServer& aServer); ~CEirPublisherTxPowerLevel(); void UpdateTxPowerLevel(TInt8 aTxPowerLevel); private: CEirPublisherTxPowerLevel(); - void ConstructL(); + void ConstructL(CEirManServer& aServer); - // From MEirPublisherNotifier - virtual void MepnSpaceAvailable(TUint aBytesAvailable); - virtual void MepnSetDataError(TInt aResult); - + // From MEirInternalSessionNotifier + virtual void MeisnSpaceAvailable(TUint aBytesAvailable); + virtual void MeisnRegisterComplete(TInt aResult); + virtual void MeisnSetDataError(TInt aError); + private: TInt8 iTxPowerLevel; TBuf8 iPublishBuf; + CEirManInternalSession* iSession; + TBool iTxPowerLevelPublished; + TBool iTagRegistered; }; #endif //EIRPUBLISHERTXPOWERLEVEL_H diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/linkmgr/linkmgr.cpp --- a/bluetooth/btstack/linkmgr/linkmgr.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/linkmgr/linkmgr.cpp Tue May 25 13:54:55 2010 +0300 @@ -652,8 +652,8 @@ void CLinkMgrProtocol::ExternalOpenInit() { LOG_FUNC - TRAP_IGNORE(iLocalNamePublisher = CEirPublisherLocalName::NewL()); - TRAP_IGNORE(iTxPowerLevelPublisher = CEirPublisherTxPowerLevel::NewL()); + TRAP_IGNORE(iLocalNamePublisher = CEirPublisherLocalName::NewL(*iEirManServer)); + TRAP_IGNORE(iTxPowerLevelPublisher = CEirPublisherTxPowerLevel::NewL(*iEirManServer)); if(iLocalNamePublisher) { // Publish the initial name. diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/linkmgr/linkmgr.h --- a/bluetooth/btstack/linkmgr/linkmgr.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/linkmgr/linkmgr.h Tue May 25 13:54:55 2010 +0300 @@ -128,14 +128,17 @@ void Error(TInt anError,CProtocolBase* aSourceProtocol=NULL); +public: // from CProtocolBase + // Ref Counting + void Close(); + void Open(); + private: // From CProtocolBase // Factories CHostResolvProvdBase* NewHostResolverL(); CServProviderBase* NewSAPL(TUint aSockType); // Ref Counting - void Close(); - void Open(); void CloseNow(); // Others diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/linkmgr/physicallinks.cpp --- a/bluetooth/btstack/linkmgr/physicallinks.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/linkmgr/physicallinks.cpp Tue May 25 13:54:55 2010 +0300 @@ -927,7 +927,12 @@ void CPhysicalLink::ConnectionComplete(THCIErrorCode aErr, const TBTConnect& aConn) { LOG_FUNC - if (aErr == KErrNone) + ConnectionComplete(CHciUtil::SymbianErrorCode(aErr), aConn); + } + +void CPhysicalLink::ConnectionComplete(TInt aResult, const TBTConnect& aConn) + { + if (aResult == KErrNone) { if(aConn.iLinkType == ESCOLink && !iSyncLogicalLink) { @@ -936,12 +941,9 @@ //a remote device to respond to a connection request. iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType); - if(aErr==EOK) // if error, aConn.iConnH will refer to the ACL link used to initialise the SCO link, so dont disconnect that - { - //The baseband might actually have established a SCO link, so send a Disconnect. - //If no SCO link exists the command will fail gracefully. - TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection)); - } + //The baseband might actually have established a SCO link, so send a Disconnect. + //If no SCO link exists the command will fail gracefully. + TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection)); return; } @@ -989,7 +991,7 @@ if (aConn.iEncryptMode) { // pretend there's been an encryption event - EncryptionChange(aErr, aConn.iConnH, aConn.iEncryptMode); + EncryptionChange(EOK, aConn.iConnH, aConn.iEncryptMode); } } @@ -1061,13 +1063,13 @@ } iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType); - NotifyLogicalLinkError(aConn.iLinkType, CHciUtil::SymbianErrorCode(aErr)); + NotifyLogicalLinkError(aConn.iLinkType, aResult); if (aConn.iLinkType == EACLLink) { // BT 1.2 says that as the ACL Link goes up and down, so does the physical link // so if the ACL Link has gone, so has this // for SCO we remain in place. - TBTBasebandEventNotification event(ENotifyPhysicalLinkError, CHciUtil::SymbianErrorCode(aErr)); + TBTBasebandEventNotification event(ENotifyPhysicalLinkError, aResult); NotifyStateChange(event); delete this; } @@ -1700,73 +1702,60 @@ { LOG_FUNC if (!IsConnected()) + { + LOG(_L8("Physical link not connected, no arbitration executed")); return KErrDisconnected; - - if ( aImmediately ) - { - iArbitrationDelay->Cancel(); - return DoArbitrate(aLocalPriority); } - else if (iArbitrationDelay->IsActive()) - { - return KErrNone; - } - else - { - iArbitrationDelay->Start(aLocalPriority); - return KErrNone; - } + // The arbitration delay object will decide how much delay + return iArbitrationDelay->Start(aImmediately, aLocalPriority); } TInt CPhysicalLink::DoArbitrate(TBool aLocalPriority) { + LOG_FUNC if (!IsConnected()) { + LOG(_L8("Physical link not connected, no arbitration executed")); return KErrDisconnected; } //start arbitrate process with what our local controller supports TUint8 allowedModesMask = EHoldMode | EParkMode | ESniffMode; // local features sorted out later - TBool roleSwitchAllowed = EFalse; - - if (iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally() && iLinksMan.RoleSwitchAllowed()) - { - roleSwitchAllowed = ETrue; - } - + TBool roleSwitchAllowed = iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally() && iLinksMan.RoleSwitchAllowed(); + LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - Prior to proxies"), allowedModesMask, roleSwitchAllowed); + // ask proxies what they want from the PHY - TUint8 requestedModeMask = 0; - TUint8 requestedMode = 0; - TBool activeModeIsRequested = EFalse; + TUint16 requestedModeMask = 0; // mask of current LPM requests from proxy's + static const TUint16 KExplicitActiveMode = 0x0100; // special bit for explicit active mode requests + TSglQueIter iter(iProxySAPs); while (iter) { CBTProxySAP* proxy = iter++; - requestedMode = proxy->GetRequestedModes(); - requestedModeMask |= requestedMode; - - if (requestedMode == EActiveMode && proxy->RequestedActiveMode()) - { - // An Active Mode request will override all other local low power mode requests - // but continue to collect the requirement from the other proxies.. - activeModeIsRequested = ETrue; - } - - allowedModesMask &= proxy->GetAllowedModes(); - roleSwitchAllowed &= proxy->IsRoleSwitchAllowed(); + TUint8 requestedMode = proxy->GetRequestedModes(); + requestedModeMask |= requestedMode; + + TBool explicitActiveModeRequest = proxy->RequestedActiveMode(); + if (requestedMode == EActiveMode && explicitActiveModeRequest) + { + requestedModeMask |= KExplicitActiveMode; + } + + TUint8 allowedModes = proxy->GetAllowedModes(); + allowedModesMask &= allowedModes; + + TBool roleSwitchAllowedByProxy = proxy->IsRoleSwitchAllowed(); + roleSwitchAllowed = roleSwitchAllowed && roleSwitchAllowedByProxy; + + LOG4(_L8("Arbitration: Proxy(0x%08x) - requested mode = 0x%04x, link policy (LPM:0x%02x, Role:0x%x)"), proxy, requestedMode, allowedModes, roleSwitchAllowedByProxy); } - - if (activeModeIsRequested) - { - // Any Active Mode request will override all other low power mode requests, - // so overwrite the requestedModeMask but keep allowedModesMask and roleSwitchAllowed - // as specified by all the local proxies - requestedModeMask = EActiveMode; - } + LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - after proxies"), allowedModesMask, roleSwitchAllowed); // clear out modes not supported by local Controller + // Future improvement - what about modes supported by the remote device? allowedModesMask &= iLinksMan.LinkManagerProtocol().ModesSupportedLocally(); + LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - only supported modes"), allowedModesMask, roleSwitchAllowed); if(iOverrideParkRequests) { @@ -1774,13 +1763,11 @@ // The only way to guarantee this is to disallow PARK via the link policy settings. allowedModesMask &= ~EParkMode; } - - if(allowedModesMask != iLinkPolicy.LowPowerModePolicy() - || roleSwitchAllowed != iLinkPolicy.IsSwitchAllowed()) - { - // Controller policy for the connection needs updating - SetModesAllowed(allowedModesMask, roleSwitchAllowed); - } + LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - overrides applied"), allowedModesMask, roleSwitchAllowed); + + // Controller policy for the connection may need updating + SetModesAllowed(allowedModesMask, roleSwitchAllowed); + LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - submitted"), allowedModesMask, roleSwitchAllowed); //If OverrideLPM flag is set, we do not disable LP modes via the link policy settings //This is done because OverrideLPM should not prevent remotes putting us into an LPM @@ -1790,9 +1777,11 @@ // We need to ensure the physical link is in active mode. allowedModesMask = EActiveMode; } - - TUint8 modeChangeMask = static_cast(requestedModeMask & allowedModesMask); - TUint8 modeCompareMask = 0; + LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - post setting overrides applied"), allowedModesMask, roleSwitchAllowed); + + TUint16 modeChangeMask = requestedModeMask & (static_cast(allowedModesMask)|KExplicitActiveMode); + TUint16 modeCompareMask = 0; + LOG2(_L8("Arbitration: mode change mask = 0x%04x, local priority = 0x%x"), modeChangeMask, aLocalPriority); if(aLocalPriority) { @@ -1809,57 +1798,89 @@ // modeCompareMask should start only having zero bits where // requestedModeMask has a zero bit and iPreviousRequestedModeMask does not // i.e. a mode is newly no longer requested. - modeCompareMask = requestedModeMask | ~iPreviousRequestedModeMask; + modeCompareMask = ~((requestedModeMask ^ iPreviousRequestedModeMask) & iPreviousRequestedModeMask); // Remove bits from modeCompareMask that are not in allowedModesMask // We cannot stay in a power mode that we do not allow. - modeCompareMask &= allowedModesMask; + modeCompareMask &= (static_cast(allowedModesMask)|KExplicitActiveMode); } + LOG1(_L8("Arbitration: Comparison mask = 0x%04x"), modeCompareMask); iPreviousRequestedModeMask = requestedModeMask; // Update previous requested to current value. - TUint8 currentModeMask = static_cast(iLinkState.LinkMode()); + // get the current mode. + TBTLinkMode currentMode = iLinkState.LinkMode(); + TUint16 currentModeMask = static_cast(currentMode); + if(currentModeMask == EActiveMode) + { + // if in active mode then could have been because of an explicit active mode request + currentModeMask |= KExplicitActiveMode; + } + LOG1(_L8("Arbitration: Current mode mask = 0x%04x"), currentModeMask); + if(modeCompareMask & currentModeMask) { + LOG2(_L8("Arbitration: Comparison mask (0x%04x) matched, so staying in current mode (0x%04x)"), modeCompareMask, currentModeMask); // The current state is the same as the permitted required role(s). return KErrNone; } - - if(modeChangeMask == EActiveMode && currentModeMask != EActiveMode) + + TBTLinkMode nextMode = EActiveMode; + // Determine which LPM we should be in (if any) + if(modeChangeMask & KExplicitActiveMode) { - // The current low power mode should be exited. - return RequestActive(); + nextMode = EActiveMode; } - - if(modeChangeMask != EActiveMode) + else if(modeChangeMask & EHoldMode) + { + nextMode = EHoldMode; + } + else if(modeChangeMask & ESniffMode) { - if(currentModeMask != EActiveMode) + nextMode = ESniffMode; + } + else if(modeChangeMask & EParkMode) + { + nextMode = EParkMode; + } + LOG2(_L8("Arbitration: Arbitrating mode 0x%02x -> 0x%02x"), currentMode, nextMode); + + if(nextMode != currentMode) + { + if(currentMode != EActiveMode) { - // The system is currently in a low power mode. Exit this before - // entering the new mode. - TInt rerr = RequestActive(); - if(rerr != KErrNone) + LOG(_L8("Arbitration: Exiting existing LPM mode...")); + TInt err = RequestActive(); + if(err != KErrNone) { - return rerr; + return err; } } - - if(modeChangeMask & EHoldMode) + if(nextMode == EHoldMode) { + LOG(_L8("Arbitration: Entering Hold mode...")); return RequestHold(); } - if(modeChangeMask & ESniffMode) + else if(nextMode == ESniffMode) { + LOG(_L8("Arbitration: Entering Sniff mode...")); return RequestSniff(); } - if(modeChangeMask & EParkMode) + else if(nextMode == EParkMode) { + LOG(_L8("Arbitration: Entering Park mode...")); return RequestPark(); } + else if(nextMode == EActiveMode) + { + LOG(_L8("Arbitration: Staying in Active mode...")); + return KErrNone; + } + // Shouldn't reach here, we have a strange mode + DEBUG_PANIC_LINENUM; } - // This point in the code is reached if the Link Policy settings are - // changed but the mode is not. Return OK error code. + LOG(_L8("Arbitration: Already in correct LPM, not doing anything")); return KErrNone; } @@ -1880,10 +1901,10 @@ void CPhysicalLink::StartArbitrationTimer() const { LOG_FUNC - iArbitrationDelay->Start(); + iArbitrationDelay->Restart(); } -TInt CPhysicalLink::Connect(TBasebandPageTimePolicy aPolicy) +void CPhysicalLink::Connect(TBasebandPageTimePolicy aPolicy) { LOG_FUNC // assume that we will be master until told otherwise @@ -1902,16 +1923,20 @@ // optimise paging (as a best-effort attempt). TBasebandTime pagetimeout = CalculatePageTimeout(aPolicy, psrm, clockOffset & KHCIClockOffsetValidBit); iLinksMan.TryToChangePageTimeout(pagetimeout); + + // Set state in anticipation of the connection + iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending); + iLinksMan.Baseband().UpdateModel(iDevice.Address(), pkt, EACLLink); + iLinkState.SetLinkRole(EMaster); TRAPD(ret, iLinksMan.HCIFacade().ConnectL(iDevice.Address(), pkt, psrm, psm, clockOffset, allowRoleSwitch)); - if(ret==KErrNone) + if(ret != KErrNone) // a physical link is in charge of it's own destiny. { - iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending); - iLinksMan.Baseband().UpdateModel(iDevice.Address(), pkt, EACLLink); - iLinkState.SetLinkRole(EMaster); + TBTConnect conn; + conn.iBdaddr = BDAddr(); + conn.iLinkType = EACLLink; + ConnectionComplete(ret, conn); } - - return ret; } TInt CPhysicalLink::SCOConnect() @@ -2264,7 +2289,7 @@ (aEvent.EventType() & ENotifyHoldMode)) && (aEvent.ErrorCode() == KErrNone)) { - iArbitrationDelay->Start(); + iArbitrationDelay->Restart(); } } @@ -3378,17 +3403,18 @@ // CArbitrationDelayTimer CArbitrationDelayTimer::CArbitrationDelayTimer(CPhysicalLink* aParent) - :CTimer(CActive::EPriorityStandard), - iParent(aParent) + : CTimer(CActive::EPriorityStandard) + , iParent(aParent) { LOG_FUNC + ASSERT_DEBUG(iParent); + CActiveScheduler::Add(this); } void CArbitrationDelayTimer::ConstructL() { LOG_FUNC CTimer::ConstructL(); - CActiveScheduler::Add(this); } CArbitrationDelayTimer* CArbitrationDelayTimer::NewL(CPhysicalLink* aParent) @@ -3401,16 +3427,46 @@ return self; } -void CArbitrationDelayTimer::Start(TBool aLocalPriority) +TInt CArbitrationDelayTimer::Start(TBool aImmediate, TBool aLocalPriority) { LOG_FUNC // Work out what the local priority will be now - TBool localPriority = iLocalPriority || aLocalPriority; - Cancel(); // cancel current timer (will also reset priority so ... - iLocalPriority = localPriority; // set the new priority) + iLocalPriority = iLocalPriority || aLocalPriority; + LOG1(_L8("Arbitraion: Local Priority now %d"), iLocalPriority); + if(aImmediate) + { + LOG(_L8("Arbitraion: Immediate Arbitration Requested...")); + CancelButPreserveLocalPriority(); + return DoArbitrate(); + } + else if(!IsActive()) + { + LOG(_L8("Arbitraion: Arbitration requested, will execute after delay timer...")); + After(KBTArbitrationDelay); + } + else // timer is already on its way + { + LOG(_L8("Arbitraion: Arbitration delay timer still pending...")); + } + return KErrNone; + } + +void CArbitrationDelayTimer::Restart() + { + LOG_FUNC + LOG(_L8("Arbitraion: Arbitration timer restarted...")); + CancelButPreserveLocalPriority(); After(KBTArbitrationDelay); } +void CArbitrationDelayTimer::CancelButPreserveLocalPriority() + { + LOG_FUNC + TBool localPriority = iLocalPriority; + Cancel(); + iLocalPriority = localPriority; + } + void CArbitrationDelayTimer::RunL() /** @@ -3418,10 +3474,16 @@ **/ { LOG_FUNC - if (iParent) - { - iParent->DoArbitrate(iLocalPriority); - } + LOG(_L8("Arbitraion: Delayed Arbitration executing...")); + static_cast(DoArbitrate()); // ignore the error (always has been...) + } + +TInt CArbitrationDelayTimer::DoArbitrate() + { + LOG_FUNC + TBool localPriority = iLocalPriority; + iLocalPriority = EFalse; + return iParent->DoArbitrate(localPriority); } void CArbitrationDelayTimer::DoCancel() diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/linkmgr/physicallinks.h --- a/bluetooth/btstack/linkmgr/physicallinks.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/linkmgr/physicallinks.h Tue May 25 13:54:55 2010 +0300 @@ -70,17 +70,20 @@ { public: static CArbitrationDelayTimer* NewL(CPhysicalLink* aParent); - void Start(TBool aLocalPriority=EFalse); - + TInt Start(TBool aImmediate, TBool aLocalPriority); + void Restart(); + private: CArbitrationDelayTimer(CPhysicalLink* aParent); void ConstructL(); void RunL(); - void DoCancel(); - + void DoCancel(); + TInt DoArbitrate(); + void CancelButPreserveLocalPriority(); + private: - CPhysicalLink* iParent; - TBool iLocalPriority; + CPhysicalLink* iParent; + TBool iLocalPriority; }; @@ -296,15 +299,14 @@ inline TBTBasebandRole Role() const; void SetDeviceNamePending(TBool aBool); TInt GetOption(TUint aLevel,TUint aName,TDes8& aOption) const; - TInt Connect(TBasebandPageTimePolicy aPolicy=EPagingNormal); + void Connect(TBasebandPageTimePolicy aPolicy=EPagingNormal); TInt SCOConnect(); TInt SCOConnect(const TUint16 aUserHVPacketTypes); TInt SynchronousConnect(TUint aTransmitBandwidth, TUint aReceiveBandwidth, TUint16 aMaxLatency, TUint16 aVoiceSettings, TUint8 aRetransmissionEffort, const TBTSyncPacketTypes aUserPacketTypes); - TInt PassiveOpen(); - TInt Arbitrate(TBool aImmediately=EFalse, TBool aLocalPriority=EFalse); - TInt DoArbitrate(TBool aLocalPriority); + TInt Arbitrate(TBool aImmediately=EFalse, TBool aLocalPriority=EFalse); + TInt DoArbitrate(TBool aLocalPriority); void SetPassKey(const TDesC8& aPassKey); const TBTPinCode& PassKey() const; @@ -374,6 +376,8 @@ virtual void RoleChange(THCIErrorCode aErr, const TBTDevAddr& aAddr, TBTBasebandRole aRole); virtual void ClockOffset(THCIErrorCode aErr, THCIConnHandle aConnH, TBasebandTime aClockOffset); virtual void RemoteName(THCIErrorCode aErr, const TBTDevAddr& aAddr, const TBTDeviceName8& aName); + + void ConnectionComplete(TInt aResult, const TBTConnect& aConn); TBool LinkKeyRequestPending(); void SetAuthenticationPending(TUint8 aFlag); @@ -553,7 +557,7 @@ TDeltaTimerEntry iOverrideLPMTimerEntry; TLinkPolicy iLinkPolicy; - TUint8 iPreviousRequestedModeMask; + TUint16 iPreviousRequestedModeMask; TBool iOverrideParkRequests; //for maybe temporary unpark TBool iOverrideLPMRequests; //for maybe temporary force active TBool iLPMOverrideTimerQueued; diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/rfcomm/rfcommmuxchannel.cpp --- a/bluetooth/btstack/rfcomm/rfcommmuxchannel.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/rfcomm/rfcommmuxchannel.cpp Tue May 25 13:54:55 2010 +0300 @@ -210,6 +210,11 @@ { return EFalse; } + +TBool TMuxChannelState::IsErrored(CRfcommMuxChannel& /*aContext*/) + { + return EFalse; + } void TMuxChannelState::UA(CRfcommMuxChannel& /*aContext*/) /** @@ -463,6 +468,11 @@ return EFalse; } +TBool TMuxChannelStateError::IsErrored(CRfcommMuxChannel& /*aContext*/) + { + return ETrue; + } + /* Connected. Super state for several states */ diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/rfcomm/rfcommmuxchannel.h --- a/bluetooth/btstack/rfcomm/rfcommmuxchannel.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/rfcomm/rfcommmuxchannel.h Tue May 25 13:54:55 2010 +0300 @@ -89,6 +89,7 @@ void Open(); void Close(); TBool IsOpen(); + TBool IsErrored(); TInt MaxDataSize(); // Rfcomm events @@ -142,6 +143,7 @@ virtual void Open(CRfcommMuxChannel& aContext); virtual void Close(CRfcommMuxChannel& aContext); virtual TBool IsOpen(CRfcommMuxChannel& aContext); + virtual TBool IsErrored(CRfcommMuxChannel& aContext); virtual void UA(CRfcommMuxChannel& aContext); virtual void DISC(CRfcommMuxChannel& aContext); virtual void DM(CRfcommMuxChannel& aContext); @@ -221,6 +223,7 @@ void Open(CRfcommMuxChannel& aContext); void Close(CRfcommMuxChannel& aContext); TBool CanAttachSAP(); + TBool IsErrored(CRfcommMuxChannel& aContext); }; /** diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/rfcomm/rfcommmuxchannel.inl --- a/bluetooth/btstack/rfcomm/rfcommmuxchannel.inl Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/rfcomm/rfcommmuxchannel.inl Tue May 25 13:54:55 2010 +0300 @@ -28,6 +28,11 @@ return iState->IsOpen(*this); } +inline TBool CRfcommMuxChannel::IsErrored() + { + return iState->IsErrored(*this); + } + inline TInt CRfcommMuxChannel::MaxDataSize() { return iMaxDataSize; diff -r 9f17f914e828 -r 32ba20339036 bluetooth/btstack/rfcomm/rfcommmuxer.cpp --- a/bluetooth/btstack/rfcomm/rfcommmuxer.cpp Tue May 11 17:15:36 2010 +0300 +++ b/bluetooth/btstack/rfcomm/rfcommmuxer.cpp Tue May 25 13:54:55 2010 +0300 @@ -209,9 +209,17 @@ DequeIdleTimer(); iSAPs.AddFirst(aSAP); if(iMuxChannel->IsOpen()) + { aSAP.MuxUp(); + } + else if (iMuxChannel->IsErrored()) + { + aSAP.Error(KErrRfcommMuxChannelErrored, CRfcommSAP::EErrorFatal); + } else + { iMuxChannel->Open(); // Eventually calls back + } } void CRfcommMuxer::DetachSAP(CRfcommSAP& aSAP) diff -r 9f17f914e828 -r 32ba20339036 bluetoothmgmt/bluetoothclientlib/inc/bt_sock.h --- a/bluetoothmgmt/bluetoothclientlib/inc/bt_sock.h Tue May 11 17:15:36 2010 +0300 +++ b/bluetoothmgmt/bluetoothclientlib/inc/bt_sock.h Tue May 25 13:54:55 2010 +0300 @@ -615,6 +615,7 @@ const static TInt KErrRfcommParameterNegotiationFailure = KRFErrorBase-7; /*!< RFCOMM parameter negotiation failure error code. */ const static TInt KErrRfcommNotListening = KRFErrorBase-8; /*!< RFCOMM not listening error code. */ const static TInt KErrRfcommNoMoreServerChannels = KRFErrorBase-9; /*!< RFCOMM no more server channels available error code. */ +const static TInt KErrRfcommMuxChannelErrored = KRFErrorBase-10; /*!< RFCOMM Mux channel errored */ //RFCOMMIoctls diff -r 9f17f914e828 -r 32ba20339036 bt_plat/bluetooth_audio_adaptation_api/inc/btaudiostreaminputbase.h --- a/bt_plat/bluetooth_audio_adaptation_api/inc/btaudiostreaminputbase.h Tue May 11 17:15:36 2010 +0300 +++ b/bt_plat/bluetooth_audio_adaptation_api/inc/btaudiostreaminputbase.h Tue May 25 13:54:55 2010 +0300 @@ -21,7 +21,7 @@ #include #include -#include +#include /** * Observer interface for receiving the audio data buffers.