bluetooth/btstack/eirman/eirmansession.cpp
changeset 0 29b1cd4cb562
child 17 32ba20339036
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // EIR Manager server session.
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22 
       
    23 #include "eirmansession.h"
       
    24 #include <bluetooth/logger.h>
       
    25 #include <bluetooth/eirmanshared.h>
       
    26 #include <bttypes.h>
       
    27 #include <bluetooth/hci/hciconsts.h>
       
    28 #include "eirmanpanics.h"
       
    29 #include "eirmanserver.h"
       
    30 
       
    31 #ifdef __FLOG_ACTIVE
       
    32 _LIT8(KLogComponent, LOG_COMPONENT_EIRMANAGER);
       
    33 #endif
       
    34 
       
    35 CEirManSession* CEirManSession::NewL(CEirManServer& aServer)
       
    36 	{
       
    37 	LOG_STATIC_FUNC
       
    38 	CEirManSession* self = new(ELeave) CEirManSession(aServer);
       
    39 	CleanupStack::PushL(self);
       
    40 	self->ConstructL();
       
    41 	CleanupStack::Pop(self);
       
    42 	return self;
       
    43 	}
       
    44 
       
    45 CEirManSession::CEirManSession(CEirManServer& aServer)
       
    46 	: iEirManServer(aServer)
       
    47 	, iEirTag(EEirTagRESERVED)
       
    48 	{
       
    49 	LOG_FUNC
       
    50 	}
       
    51 
       
    52 void CEirManSession::ConstructL()
       
    53 	{
       
    54 	LOG_FUNC
       
    55 	iEirManServer.AddSession();
       
    56 	}
       
    57 
       
    58 CEirManSession::~CEirManSession()
       
    59 	{
       
    60 	LOG_FUNC
       
    61 	// deregister any registered tag that may be registered
       
    62 	DeregisterTag();
       
    63 	if(!iDataAvailableListenerMessage.IsNull())
       
    64 		{
       
    65 		// complete any outstanding messages.
       
    66 		iDataAvailableListenerMessage.Complete(KErrCancel);
       
    67 		}
       
    68 	iEirManServer.DropSession();
       
    69 	}
       
    70 
       
    71 void CEirManSession::ServiceL(const RMessage2& aMessage)
       
    72 	{
       
    73 	LOG_FUNC
       
    74 	LOG1(_L("CEirManSession::ServiceL aMessage.Function() = %d"), aMessage.Function());
       
    75 	TBool complete = ETrue;
       
    76 	TInt ret = KErrNone;
       
    77 
       
    78 	switch (aMessage.Function())
       
    79 		{
       
    80 	case EEirManRegisterTag:
       
    81 		complete = EFalse; // always async.
       
    82 		RegisterTag(aMessage);
       
    83 		break;
       
    84 
       
    85 	case EEirManSpaceAvailableNotification:
       
    86 		ret = RegisterSpaceAvailableListener(aMessage, complete);
       
    87 		break;
       
    88 
       
    89 	case EEirManCancelSpaceAvailableNotification:
       
    90 		ret = CancelSpaceAvailableListener();
       
    91 		break;
       
    92 
       
    93 	case EEirManSetData:
       
    94 		ret = SetData(aMessage);
       
    95 		break;
       
    96 		
       
    97 	case EEirManNewData:
       
    98 		ret = NewData(aMessage);
       
    99 		break;
       
   100 
       
   101 	default:
       
   102 		aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidIPC);
       
   103 		break;
       
   104 		}
       
   105 
       
   106 	if (complete)
       
   107 		{
       
   108 		aMessage.Complete(ret);
       
   109 		}
       
   110 	}
       
   111 
       
   112 void CEirManSession::RegisterTag(const RMessage2& aMessage)
       
   113 	{
       
   114 	LOG_FUNC
       
   115 
       
   116 	TEirTag tag = static_cast<TEirTag>(aMessage.Int0());
       
   117 	LOG1(_L("CEirManSession::RegisterTag tag = %d"), tag);
       
   118 
       
   119 	if(!(tag >= EEirTagName && tag < EEirTagRESERVED))
       
   120 		{
       
   121 		__ASSERT_ALWAYS(EFalse, aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidTag));
       
   122 		}
       
   123 	else if(iEirTag != EEirTagRESERVED)
       
   124 		{
       
   125 		LOG1(_L("CEirManSession::RegisterTag ERROR, Tag in use: %d"), iEirTag);
       
   126 		aMessage.Complete(KErrInUse);
       
   127 		}
       
   128 	else
       
   129 		{
       
   130 		// Register this tag for callbacks
       
   131 		if(iEirManServer.EirFeatureState() == EEirFeatureReady)
       
   132 			{
       
   133 			// Eir is supported
       
   134 			TInt result = iEirManServer.EirManager().RegisterTag(tag, *this);
       
   135 			if(result == KErrNone)
       
   136 				{
       
   137 				iEirTag = tag;
       
   138 				}
       
   139 			aMessage.Complete(result);
       
   140 			}
       
   141 		else if(iEirManServer.EirFeatureState() == EEirFeaturePending)
       
   142 			{
       
   143 			// We don't know if eir is supported or not at this moment
       
   144 			iPendingEirTag = tag;
       
   145 			iRegisterMessage = aMessage;
       
   146 			}
       
   147 		else
       
   148 			{
       
   149 			// Eir is not supported
       
   150 			aMessage.Complete(KErrNotSupported);
       
   151 			}
       
   152 		}
       
   153 	}
       
   154 
       
   155 void CEirManSession::DeregisterTag()
       
   156 	{
       
   157 	LOG_FUNC
       
   158 	LOG1(_L("CEirManSession::DeregisterTag tag = %d"), iEirTag);
       
   159 	
       
   160 	if(iEirTag != EEirTagRESERVED)
       
   161 		{
       
   162 		// Deregister this tag for callbacks 
       
   163 		iEirManServer.EirManager().DeregisterTag(iEirTag);
       
   164 		iEirTag = EEirTagRESERVED;
       
   165 		}
       
   166 	}
       
   167 
       
   168 // Eir Server has tried to register tag
       
   169 void CEirManSession::NotifyEirFeatureState(TInt aResult)
       
   170 	{
       
   171 	LOG1(_L("Eir Server has been notified feature ready, result: %d"), aResult);
       
   172 	if(aResult == KErrNone && !iRegisterMessage.IsNull())
       
   173 		{
       
   174 		__ASSERT_DEBUG(iEirManServer.EirFeatureState() == EEirFeatureReady, EIR_SESSION_PANIC(EEirSessionEirFeatureNotSupported));
       
   175 		TInt result = iEirManServer.EirManager().RegisterTag(iPendingEirTag, *this);
       
   176 		if(result == KErrNone)
       
   177 			{
       
   178 			iEirTag = iPendingEirTag;
       
   179 			}
       
   180 		iRegisterMessage.Complete(result);
       
   181 		}
       
   182 	else if(!iRegisterMessage.IsNull())
       
   183 		{
       
   184 		iRegisterMessage.Complete(aResult);
       
   185 		}
       
   186 	}
       
   187 
       
   188 TInt CEirManSession::RegisterSpaceAvailableListener(const RMessage2& aMessage, TBool& aComplete)
       
   189 	{
       
   190 	LOG_FUNC
       
   191 
       
   192 	if(iDataAvailableListenerMessage.Handle())
       
   193 		{
       
   194 		LOG(_L("CEirManSession:::RegisterSpaceAvailableListener ERROR IN USE"));
       
   195 		return KErrInUse;
       
   196 		}
       
   197 
       
   198 	iDataAvailableListenerMessage = aMessage;
       
   199 
       
   200 	aComplete = EFalse;
       
   201 
       
   202 	if(iLastSpaceOffered != 0)
       
   203 		{
       
   204 		LOG(_L("cached space present, completing immediately"));
       
   205 		CompleteSpaceAvailableRequest(iLastSpaceOffered);
       
   206 		iLastSpaceOffered = 0;
       
   207 		return KErrNone;
       
   208 		}
       
   209 	
       
   210 	LOG(_L("waiting for callback..."));
       
   211 	return KErrNone;
       
   212 	}
       
   213 	
       
   214 TInt CEirManSession::NewData(const RMessage2& aMessage)
       
   215 	{
       
   216 	LOG_FUNC
       
   217 	__ASSERT_ALWAYS(iEirTag != EEirTagRESERVED, aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidTag));
       
   218 	TInt requiredLength = static_cast<TInt>(aMessage.Int0());
       
   219 
       
   220 	return iEirManServer.EirManager().NewData(iEirTag, requiredLength);
       
   221 	}
       
   222 
       
   223 TInt CEirManSession::CancelSpaceAvailableListener()
       
   224 	{
       
   225 	LOG_FUNC
       
   226 
       
   227 	if(!iDataAvailableListenerMessage.Handle())
       
   228 		{
       
   229 		return KErrNotFound;
       
   230 		}
       
   231 
       
   232 	iDataAvailableListenerMessage.Complete(KErrCancel);
       
   233 
       
   234 	return KErrNone;
       
   235 	}
       
   236 
       
   237 TInt CEirManSession::SetData(const RMessage2& aMessage)
       
   238 	{
       
   239 	LOG_FUNC
       
   240 	__ASSERT_ALWAYS(iEirTag != EEirTagRESERVED, aMessage.Panic(KEirManCliPncCat, EEirManPanicInvalidTag));
       
   241 	TEirDataMode eirDataMode = static_cast<TEirDataMode>(aMessage.Int1());
       
   242 	LOG2(_L("Tag: %d EirDataMode: %d"), iEirTag, eirDataMode);
       
   243 
       
   244 	// No need to allocate memory with an expensive malloc() call (via HBuf8::NewL or whatever), 
       
   245 	// since the EIR contents fit in the stack, and the EIR Manager will cache the data anyway
       
   246 	TBuf8<KHCIExtendedInquiryResponseMaxLength> data;
       
   247 	TInt err = aMessage.Read(0, data);
       
   248 	
       
   249 	if(err == KErrNone)
       
   250 		{
       
   251 		err = iEirManServer.EirManager().SetData(iEirTag, data, eirDataMode);
       
   252 		}
       
   253 	return err;
       
   254 	}
       
   255 
       
   256 // Callback from the EIR Manager
       
   257 void CEirManSession::MemnEirBlockAvailable(TEirTag aTag, TUint aSpaceForTag)
       
   258 	{
       
   259 	LOG_FUNC
       
   260 	LOG2(_L("CEirManSession::MemnEirBlockAvailable Tag: %d space: %d"), aTag, aSpaceForTag);
       
   261 
       
   262 	// Silently discard callbacks not containing our EIR Tag
       
   263 	if(aTag != iEirTag)
       
   264 		{
       
   265 		__ASSERT_DEBUG(EFalse, EIR_SESSION_PANIC(EEirSessionInvalidEirTag));
       
   266 		LOG3(_L("CEirManSession::MemnEirBlockAvailable early return: aTag: %d iEirTag: %d space: %d"), aTag, iEirTag, aSpaceForTag);
       
   267 		return;
       
   268 		}
       
   269 
       
   270 	if(iDataAvailableListenerMessage.Handle())
       
   271 		{
       
   272 		LOG(_L("Listener outstanding, completing request"));
       
   273 		// Clear stored value
       
   274 		iLastSpaceOffered = 0;
       
   275 		CompleteSpaceAvailableRequest(aSpaceForTag);
       
   276 		}
       
   277 	else
       
   278 		{
       
   279 		LOG(_L("NO Listener outstanding, storing space"));
       
   280 		// Store in case a client registers later. If this happens multiple times, only the last one will be remembered
       
   281 		iLastSpaceOffered = aSpaceForTag;
       
   282 		}
       
   283 	}
       
   284 
       
   285 void CEirManSession::CompleteSpaceAvailableRequest(TUint aBytesAvailable)
       
   286 	{
       
   287 	LOG_FUNC
       
   288 	LOG1(_L("CEirManSession::CompleteSpaceAvailableRequest bytes: %d"), aBytesAvailable);
       
   289 	// Offer the space to the client
       
   290 	TPckg<TUint32> pckg(aBytesAvailable);
       
   291 
       
   292 	TInt err = iDataAvailableListenerMessage.Write(0, pckg);
       
   293 	iDataAvailableListenerMessage.Complete(err);
       
   294 	}
       
   295