bluetoothengine/bthid/bthidserver/src/bthidsession.cpp
changeset 0 f63038272f30
child 11 a42ed326b458
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/bthid/bthidserver/src/bthidsession.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,350 @@
+/*
+* Copyright (c) 2008 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:  This is the implementation of application class
+ *
+*/
+
+
+#include <e32svr.h>
+#include <bttypes.h>
+#include "bthidsession.h"
+#include "bthidserver.h"
+#include "bthidclientsrv.h"
+#include "hidsdpclient.h"
+#include "bthiddevice.h"
+#include "bthidserver.pan"
+#include "debug.h"
+
+CBTHidServerSession::CBTHidServerSession(CBTHidServer& aServer) :
+    iServer(aServer)
+    {
+    // Implementation not required
+    }
+
+CBTHidServerSession::~CBTHidServerSession()
+    {
+    iServer.DecrementSessions();
+    delete iHidSdpClient;
+    }
+
+void CBTHidServerSession::ServiceL(const RMessage2& aMessage)
+    {
+    TRAPD( err, DispatchMessageL( aMessage ) );
+
+    if (aMessage.Function() == EBTHIDGetConnections && !aMessage.IsNull())
+        {
+        // Handle the error code, what to to?
+        err = err;
+        }
+    }
+
+void CBTHidServerSession::DispatchMessageL(const RMessage2& aMessage)
+    {
+    switch (aMessage.Function())
+        {
+        case EBTHIDServConnectDevice:
+            RequestConnectionL(aMessage);
+            break;
+
+        case EBTHIDServCancelConnect:
+            if (iConnectionMessage.Handle())
+                {
+                delete iHidSdpClient;
+                iHidSdpClient = 0;
+
+                iServer.DeleteNewConnection(iConnectingID);
+
+                iConnectionMessage.Complete(KErrCancel);
+                }
+            aMessage.Complete(KErrNone);
+            break;
+
+        case EBTHIDServNotifyConnectionChange:
+            if (iUpdateMessage.Handle())
+                {
+                // We're already busy
+                CBTHidServer::PanicClient(aMessage, EReqAlreadyPending);
+                }
+            else
+                {
+                iUpdateMessage = aMessage;
+                }
+            break;
+
+        case EBTHIDServCancelNotify:
+            if (iUpdateMessage.Handle())
+                {
+                iUpdateMessage.Complete(KErrCancel);
+                }
+            aMessage.Complete(KErrNone);
+            break;
+
+        case EBTHIDServDisconnectDevice:
+            RequestDisconnectionL(aMessage);
+            break;
+
+        case EBTHIDServIsConnected:
+            IsConnectedL(aMessage);
+            break;
+
+        case EBTHidSrvDisconnectAllGracefully:
+            if (iDisconnectMsg.Handle())
+                {
+                aMessage.Complete(KErrServerBusy);
+                }
+            else
+                {
+                iDisconnectMsg = aMessage;
+                iServer.DisconnectAllDeviceL();
+                iDisconnectMsg.Complete(KErrNone);
+                }
+            break;
+
+        case EBTHIDGetConnections:
+            GetConnections(aMessage);
+            break;
+
+        default:
+            {
+            TRACE_INFO( ( _L( "[BTHID]\t DispatchMessageL: bad request (%d)" ), 
+                                aMessage.Function() ) )
+            CBTHidServer::PanicClient(aMessage, EBadRequest);
+            }
+            break;
+        }
+    }
+
+void CBTHidServerSession::HidSdpSearchComplete(TInt aResult)
+    {
+        TRACE_FUNC
+    (_L("[BTHID]\tCBTHidServerSession::HidSdpSearchComplete"));
+    // This is a callback for the Hid SDP client so we can't delete it here
+    // Get it to destroy itself when its convenient.
+    iHidSdpClient->Kill();
+    // Deleted outside destructor.
+    iHidSdpClient = 0;
+
+    TInt err = aResult;
+
+    // If the SDP search was a success
+    if (err == KErrNone)
+        {
+            // Try to connect to the device as a HID
+            TRAP( err, iServer.DoFirstConnectionL(iConnectingID); )
+
+        if (err == KErrAlreadyExists)
+            {
+            //there is already an active connection with the same CoD
+            TBuf8<KBTDevAddrSize> buf;
+            TBTDevAddr dummyAddr = iServer.ConflictAddress();
+            buf.Append(dummyAddr.Des());
+            if (buf.Length())
+                {
+                iConnectionMessage.Write(1, buf);
+                }
+
+            //delete the connection object in the server
+            iServer.DeleteNewConnection(iConnectingID);
+            iConnectionMessage.Complete(err);
+            return;
+            }
+        }
+
+    // Any error causes clean up,
+    if (err != KErrNone)
+        {
+        //delete the connection object in the server
+        iServer.DeleteNewConnection(iConnectingID);
+
+        //Inform the client of the result
+        iConnectionMessage.Complete(aResult);
+        }
+    }
+
+void CBTHidServerSession::RequestConnectionL(const RMessage2& aMessage)
+    {
+        TRACE_FUNC
+    (_L("[BTHID]\tCBTHidServerSession::RequestConnectionL"));
+
+    if (iConnectionMessage.Handle())
+        {
+        // We're already busy
+        CBTHidServer::PanicClient(aMessage, EReqAlreadyPending);
+        }
+    else
+        {
+            TRACE_INFO(_L("[BTHID]\tCBTHidServerSession::RequestConnectionL continue to connect"));
+        // Keep a copy of message - for use later
+        iConnectionMessage = aMessage;
+
+        // Read the connection parameters
+        TBTDevAddr addr;
+        TPckg<TBTDevAddr> addrPack(addr);
+
+        iConnectionMessage.ReadL(0, addrPack);
+        // Ask the server to create a new connection object
+
+
+        iConnectingID = iServer.NewConnectionL();
+        TRAPD( res,
+                // Retrieve the hid device object for this new connection
+                CBTHidDevice &devDetails =
+                iServer.ConnectionDetailsL(iConnectingID);
+
+                // Fill in the information we got from the client
+                devDetails.iAddress = addr;
+                devDetails.iUseSecurity = ETrue;
+
+                // Create a new HID Sdp Client
+                // Its only used here so it doesn't matter if we leave.
+                delete iHidSdpClient;
+                iHidSdpClient = 0;
+                //Create a new hid sdp client using the hid device object.
+                iHidSdpClient = CHidSdpClient::NewL(devDetails, *this);
+
+                // Start the hid sdp client
+                iHidSdpClient->StartL();
+        )
+
+        // If there was any error, inform the client and finish
+        if (res != KErrNone)
+            {
+            // Get the server to delete the new connection object
+            iServer.DeleteNewConnection(iConnectingID);
+            aMessage.Complete(res);
+            }
+        }
+
+    }
+
+void CBTHidServerSession::RequestDisconnectionL(const RMessage2& aMessage)
+    {
+    TBTDevAddr addr;
+    TPckg<TBTDevAddr> addrPack(addr);
+
+    // Read the address from the client thread.
+    aMessage.ReadL(0, addrPack);
+
+    // Since the user can select this option using the BT Keyboard
+    // and the keydown event triggers it, depending on how long they
+    // hold down the key, the connection could be restored to send
+    // the key up event.
+    // Add a small delay, sensible enough for a press of the enter
+    // key before disconnection.
+    // Currently 3/4 of a second.
+    User::After(750000);
+
+    //Keep the connection alive, initial reconnect from HID device available...
+    iServer.CloseBluetoothConnection(addr);
+
+    aMessage.Complete(KErrNone);
+    }
+
+void CBTHidServerSession::InformStatusChange(
+        const THIDStateUpdateBuf& aUpdateParams)
+    {
+        TRACE_FUNC
+    (_L("[BTHID]\tCBTHidServerSession::InformStatusChange"));
+
+    THIDStateUpdate update = aUpdateParams();
+    TBTHidConnState state = update.iState;
+
+    TBuf8<KBTDevAddrSize> buf;
+    if (state == EBTDeviceAnotherExist)
+        {
+        TBTDevAddr iDumyAddr = iServer.ConflictAddress();
+        buf.Append(iDumyAddr.Des());
+        }
+
+        TRACE_INFO( (_L("[BTHID]\tCBTHidServerSession::InformStatusChange, state=%d"), state) );
+
+    if (iUpdateMessage.Handle())
+        {
+            TRACE_FUNC
+        (_L("[BTHID]\tCBTHidServerSession::InformStatusChange, OK - send message"));
+        // Trap any error
+        TRAPD( res,
+                iUpdateMessage.WriteL(0,aUpdateParams);
+                if (buf.Length())
+                    {
+                    iUpdateMessage.WriteL(1,buf);
+                    }
+        )
+
+        if (state == EBTDeviceAnotherExist)
+            {
+            iUpdateMessage.Complete(KErrAlreadyExists);
+            }
+        else
+            {
+            // Complete the message, with the error code from the trap.
+            iUpdateMessage.Complete(res);
+            }
+        }
+    }
+
+void CBTHidServerSession::InformConnectionResult(TInt aConnID, TInt aResult)
+    {
+        TRACE_INFO( (_L("[BTHID new]\tCBTHidServerSession::InformConnectionResult, Ids: %d==%d aResult = %d"),
+                        iConnectingID, aConnID, aResult) );
+    if ((iConnectionMessage.Handle()) && (iConnectingID == aConnID))
+        {
+        iConnectionMessage.Complete(aResult);
+        }
+    }
+
+void CBTHidServerSession::IsConnectedL(const RMessage2& aMessage)
+    {
+    TBTDevAddr addr;
+    TPckg<TBTDevAddr> addrPck(addr);
+    aMessage.ReadL(0, addrPck);
+    TBTEngConnectionStatus ret = iServer.ConnectStatus(addr);
+
+    aMessage.Complete(ret);
+    }
+
+void CBTHidServerSession::GetConnections(const RMessage2& aMessage)
+    {
+        TRACE_FUNC
+    TBuf8<KBTDevAddrSize * 2> buf;
+    buf.Zero();
+    iServer.GetConnectionAddress(buf);
+    if (buf.Length())
+        {
+        aMessage.Write(0, buf);
+        }
+
+    aMessage.Complete(KErrNone);
+    }
+
+CBTHidServerSession* CBTHidServerSession::NewL(CBTHidServer& aServer)
+    {
+    CBTHidServerSession* self = CBTHidServerSession::NewLC(aServer);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+CBTHidServerSession* CBTHidServerSession::NewLC(CBTHidServer& aServer)
+    {
+    CBTHidServerSession* self = new (ELeave) CBTHidServerSession(aServer);
+
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+    }
+
+void CBTHidServerSession::ConstructL()
+    {
+    iServer.IncrementSessions();
+    }