--- /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 <e32base.h>
+#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 );
+ }
+ }