bluetoothengine/bteng/src/btengsrvsession.cpp
changeset 0 f63038272f30
child 8 0707dd69d236
--- /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 );
+        }
+    }