diff -r 000000000000 -r f63038272f30 bluetoothengine/bteng/src/btengsrvsession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothengine/bteng/src/btengsrvsession.cpp Mon Jan 18 20:28:57 2010 +0200 @@ -0,0 +1,335 @@ +/* +* Copyright (c) 2006 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: Implementation of BTEng server session handling +* +*/ + + + +#include +#include "btengsrvsession.h" +#include "btengserver.h" +#include "btengsrvbbconnectionmgr.h" +#include "btengpairman.h" +#include "btengclientserver.h" +#include "debug.h" + + +/** The message argument which holds the client event package. */ +const TInt KBTEngEventSlot = 2; + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// C++ default constructor +// --------------------------------------------------------------------------- +// +CBTEngSrvSession::CBTEngSrvSession() +: CSession2() + { + } + + +// --------------------------------------------------------------------------- +// Symbian 2nd-phase constructor +// --------------------------------------------------------------------------- +// +void CBTEngSrvSession::ConstructL() + { + TRACE_FUNC_ENTRY + + //create queue for storing multiple connection events + iConnectionEventQueue = new (ELeave) CDesC8ArraySeg(1); + } + + +// --------------------------------------------------------------------------- +// NewL +// --------------------------------------------------------------------------- +// +CBTEngSrvSession* CBTEngSrvSession::NewL() + { + CBTEngSrvSession* self = new( ELeave ) CBTEngSrvSession(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CBTEngSrvSession::~CBTEngSrvSession() + { + TRACE_FUNC_ENTRY + if( !iNotifyConnMessage.IsNull() ) + { + iNotifyConnMessage.Complete( KErrCancel ); + } + CancelPairRequest(); + if( Server() ) + { + Server()->RemoveSession( iAutoSwitchOff ); + } + + delete iConnectionEventQueue; + + TRACE_FUNC_EXIT + } + + +// --------------------------------------------------------------------------- +// Complete the construction of the session. +// --------------------------------------------------------------------------- +// +void CBTEngSrvSession::CreateL() + { + TRACE_FUNC_ENTRY + Server()->AddSession(); + } + + +// --------------------------------------------------------------------------- +// Notify the client of the connection event. +// --------------------------------------------------------------------------- +// +void CBTEngSrvSession::NotifyConnectionEvent(const TBTDevAddr aAddr, + TBTEngConnectionStatus aConnStatus, RBTDevAddrArray* aArray, TInt aErr) + { + TRACE_FUNC_ENTRY + + TRACE_INFO((_L("[BTEng]\t Informing client %d"), iNotifyConnMessage.Handle())); + + //package up connection event to send to the client + TBTEngEventPkg pkg; + pkg().iAddr = aAddr; + pkg().iConnEvent = aConnStatus; + pkg().iConflictsBuf.Zero(); + if (aArray) + { + TBTDevAddrPckgBuf addr; + + for (TInt i = 0; i < aArray->Count(); i++) + { + addr = (*aArray)[i]; + pkg().iConflictsBuf.Append(addr); + } + } + + TInt err = KErrNotFound; + + //if a client message is outstanding + if (!iNotifyConnMessage.IsNull()) + { + //complete the message prioritising the main error + err = iNotifyConnMessage.Write(KBTEngEventSlot, pkg); + aErr = (aErr != KErrNone) ? aErr : err; + iNotifyConnMessage.Complete(aErr); + } + + //if there is no client message outstanding or the write failed + if (err != KErrNone) + { + //if the append fails we can't do anything with the error so ignore + //it and let the event get dropped + TRAP_IGNORE(iConnectionEventQueue->AppendL(pkg)); + } + } + +// --------------------------------------------------------------------------- +// Comfirm the caller if pairing request is completed in this invoke. +// --------------------------------------------------------------------------- +// +TInt CBTEngSrvSession::CompletePairRequest( TInt aResult ) + { + if ( !iPairMessage.IsNull()) + { + iPairMessage.Complete( aResult ); + return KErrNone; + } + return KErrNotFound; + } + +// --------------------------------------------------------------------------- +// From class CSession2 +// Handles servicing of a client request that has been passed to the server. +// --------------------------------------------------------------------------- +// +void CBTEngSrvSession::ServiceL( const RMessage2& aMessage ) + { + TRAPD( err, DispatchMessageL( aMessage ) ); + + if( !aMessage.IsNull() && + ( err || + ( aMessage.Function() != EBTEngNotifyConnectionEvents && + aMessage.Function() != EBTEngPairDevice ) ) ) + { + // Return the error code to the client. + aMessage.Complete( err ); + } + } + + +// --------------------------------------------------------------------------- +// Returns a handle to CBTEngServer. +// --------------------------------------------------------------------------- +// +CBTEngServer* CBTEngSrvSession::Server() + { + return (CBTEngServer*) CSession2::Server(); + } + + +// --------------------------------------------------------------------------- +// Handles a client request that has been passed to the server. +// --------------------------------------------------------------------------- +// +void CBTEngSrvSession::DispatchMessageL( const RMessage2& aMessage ) + { + TRACE_FUNC_ENTRY + TInt opcode = aMessage.Function(); + + switch( opcode ) + { + case EBTEngSetPowerState: + { + iAutoSwitchOff = (TBool) aMessage.Int1(); + Server()->SetPowerStateL( (TBTPowerStateValue) aMessage.Int0(), + iAutoSwitchOff ); + } + break; + case EBTEngSetVisibilityMode: + { + Server()->SetVisibilityModeL( (TBTVisibilityMode) aMessage.Int0(), + aMessage.Int1() ); + } + break; + case EBTEngNotifyConnectionEvents: + { + //ensure the message contains the correctly sized descriptor + if (aMessage.GetDesMaxLengthL(KBTEngEventSlot) != sizeof(TBTEngEventMsg)) + { + User::Leave(KErrBadDescriptor); + } + + if(!iNotifyConnMessage.IsNull()) + { + User::Leave(KErrInUse); + } + + //save the client message + iNotifyConnMessage = RMessage2(aMessage); + + //if there is an existing connection event that the client does + //not yet know about + if (iConnectionEventQueue->Count() > 0) + { + //complete straight away with package from queue + TInt err = iNotifyConnMessage.Write(KBTEngEventSlot, (*iConnectionEventQueue)[0]); + if (err == KErrNone) + { + iConnectionEventQueue->Delete(0); + } + iNotifyConnMessage.Complete(err); + } + } + break; + case EBTEngCancelEventNotifier: + { + if( !iNotifyConnMessage.IsNull() ) + { + iNotifyConnMessage.Complete( KErrCancel ); + } + } + break; + case EBTEngConnectDevice: + case EBTEngCancelConnectDevice: + case EBTEngDisconnectDevice: + case EBTEngIsDeviceConnected: + case EBTEngGetConnectedAddresses: + { + TBTPowerStateValue pwr = EBTPowerOff; + Server()->GetHwPowerState( pwr ); + if( pwr ) + { + // Simply forward it to the plug-in manager + Server()->DispatchPluginMessageL( aMessage ); + } + else + { + User::Leave( KErrNotReady ); + } + } + break; + case EBTEngIsDeviceConnectable: + { + Server()->DispatchPluginMessageL( aMessage ); + } + break; + case EBTEngPrepareDiscovery: + { + aMessage.Complete( KErrNone ); // Client does not have to wait. + Server()->iBBConnMgr->ManageTopology( ETrue ); + } + break; + case EBTEngSetPairingObserver: + case EBTEngPairDevice: + { + TBTPowerStateValue pwr = EBTPowerOff; + (void) Server()->GetHwPowerState( pwr ); + if( pwr ) + { + // Simply forward it to the pairing manager + Server()->PairManager().ProcessCommandL( aMessage ); + if ( opcode == EBTEngPairDevice ) + { + iPairMessage = RMessage2( aMessage ); + } + } + else + { + User::Leave( KErrNotReady ); + } + break; + } + case EBTEngCancelPairDevice: + { + CancelPairRequest(); + break; + } + default: + { + TRACE_INFO( ( _L( "[BTENG]\t DispatchMessageL: bad request (%d)" ), + aMessage.Function() ) ) + User::Leave( KErrArgument ); + } + break; + } + TRACE_FUNC_EXIT + } + +// --------------------------------------------------------------------------- +// Only the originator of pairing can cancel the pairing request. +// --------------------------------------------------------------------------- +// +void CBTEngSrvSession::CancelPairRequest() + { + if ( !iPairMessage.IsNull() ) + { + Server()->PairManager().CancelCommand( iPairMessage.Function() ); + iPairMessage.Complete( KErrCancel ); + } + }