diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btstack/eirman/eirmansession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/eirman/eirmansession.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,295 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// EIR Manager server session. +// +// + +/** + @file + @internalComponent +*/ + +#include "eirmansession.h" +#include +#include +#include +#include +#include "eirmanpanics.h" +#include "eirmanserver.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_EIRMANAGER); +#endif + +CEirManSession* CEirManSession::NewL(CEirManServer& aServer) + { + LOG_STATIC_FUNC + CEirManSession* self = new(ELeave) CEirManSession(aServer); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CEirManSession::CEirManSession(CEirManServer& aServer) + : iEirManServer(aServer) + , iEirTag(EEirTagRESERVED) + { + LOG_FUNC + } + +void CEirManSession::ConstructL() + { + LOG_FUNC + iEirManServer.AddSession(); + } + +CEirManSession::~CEirManSession() + { + LOG_FUNC + // deregister any registered tag that may be registered + DeregisterTag(); + if(!iDataAvailableListenerMessage.IsNull()) + { + // complete any outstanding messages. + iDataAvailableListenerMessage.Complete(KErrCancel); + } + iEirManServer.DropSession(); + } + +void CEirManSession::ServiceL(const RMessage2& aMessage) + { + LOG_FUNC + LOG1(_L("CEirManSession::ServiceL aMessage.Function() = %d"), aMessage.Function()); + TBool complete = ETrue; + TInt ret = KErrNone; + + switch (aMessage.Function()) + { + case EEirManRegisterTag: + complete = EFalse; // always async. + RegisterTag(aMessage); + break; + + case EEirManSpaceAvailableNotification: + ret = RegisterSpaceAvailableListener(aMessage, complete); + break; + + case EEirManCancelSpaceAvailableNotification: + ret = CancelSpaceAvailableListener(); + break; + + case EEirManSetData: + ret = SetData(aMessage); + break; + + case EEirManNewData: + ret = NewData(aMessage); + break; + + default: + aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidIPC); + break; + } + + if (complete) + { + aMessage.Complete(ret); + } + } + +void CEirManSession::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); + } + } + } + +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 && !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) + { + LOG_FUNC + + if(iDataAvailableListenerMessage.Handle()) + { + LOG(_L("CEirManSession:::RegisterSpaceAvailableListener ERROR IN USE")); + return KErrInUse; + } + + iDataAvailableListenerMessage = aMessage; + + aComplete = EFalse; + + if(iLastSpaceOffered != 0) + { + LOG(_L("cached space present, completing immediately")); + CompleteSpaceAvailableRequest(iLastSpaceOffered); + iLastSpaceOffered = 0; + return KErrNone; + } + + LOG(_L("waiting for callback...")); + return KErrNone; + } + +TInt CEirManSession::NewData(const RMessage2& aMessage) + { + LOG_FUNC + __ASSERT_ALWAYS(iEirTag != EEirTagRESERVED, aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidTag)); + TInt requiredLength = static_cast(aMessage.Int0()); + + return iEirManServer.EirManager().NewData(iEirTag, requiredLength); + } + +TInt CEirManSession::CancelSpaceAvailableListener() + { + LOG_FUNC + + if(!iDataAvailableListenerMessage.Handle()) + { + return KErrNotFound; + } + + iDataAvailableListenerMessage.Complete(KErrCancel); + + return KErrNone; + } + +TInt CEirManSession::SetData(const RMessage2& aMessage) + { + LOG_FUNC + __ASSERT_ALWAYS(iEirTag != EEirTagRESERVED, aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidTag)); + TEirDataMode eirDataMode = static_cast(aMessage.Int1()); + LOG2(_L("Tag: %d EirDataMode: %d"), iEirTag, 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 + TBuf8 data; + TInt err = aMessage.Read(0, data); + + if(err == KErrNone) + { + err = iEirManServer.EirManager().SetData(iEirTag, data, eirDataMode); + } + return err; + } + +// 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; + } + + if(iDataAvailableListenerMessage.Handle()) + { + LOG(_L("Listener outstanding, completing request")); + // Clear stored value + iLastSpaceOffered = 0; + CompleteSpaceAvailableRequest(aSpaceForTag); + } + else + { + LOG(_L("NO Listener outstanding, storing space")); + // Store in case a client registers later. If this happens multiple times, only the last one will be remembered + iLastSpaceOffered = aSpaceForTag; + } + } + +void CEirManSession::CompleteSpaceAvailableRequest(TUint aBytesAvailable) + { + LOG_FUNC + LOG1(_L("CEirManSession::CompleteSpaceAvailableRequest bytes: %d"), aBytesAvailable); + // Offer the space to the client + TPckg pckg(aBytesAvailable); + + TInt err = iDataAvailableListenerMessage.Write(0, pckg); + iDataAvailableListenerMessage.Complete(err); + } +