bluetoothengine/btaudioman/src/BTAccSession.cpp
changeset 0 f63038272f30
child 6 6a29d5ad0713
child 15 00f9ee97d895
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btaudioman/src/BTAccSession.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,485 @@
+/*
+* Copyright (c) 2005-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: 
+*     Server class creates the session. This class then recieves the messages from
+*      client and forward them to server class to be handled. Messages are completed
+*      with return values recieved from server. 
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32cmn.h>
+#include "BTAccSession.h"
+#include "BTAccClientSrv.h"
+#include "debug.h"
+#include "BTAccServer.h"
+#include "basrvaccman.h"
+#include "BTAccInfo.h"
+
+typedef TPckgBuf<TBTDevAddr> TBTDevAddrPckgBuf;
+
+// ================= MEMBER FUNCTIONS =======================
+CBTAccSession* CBTAccSession::NewL(CBasrvAccMan& aAccMan)
+    {
+    return new (ELeave) CBTAccSession(aAccMan);
+    }
+
+CBTAccSession::CBTAccSession(CBasrvAccMan& aAccMan) 
+    : iAccMan(aAccMan)
+    {
+    TRACE_FUNC
+    }
+
+// destructor
+CBTAccSession::~CBTAccSession()
+    {
+    TRACE_FUNC
+    if (iConnectMsg.Handle())
+        {
+        iAccMan.CancelConnect(iConnectingAddr);
+        iConnectMsg.Complete(KErrAbort);
+        }    
+    if (iDisconnectMsg.Handle())
+        {
+        iDisconnectMsg.Complete(KErrAbort);
+        }
+    if (iDisconnectAllMsg.Handle())
+        {
+        iDisconnectAllMsg.Complete(KErrAbort);
+        }
+    if (iNotifyProfileMsg.Handle())
+        {
+        iNotifyProfileMsg.Complete(KErrAbort);
+        }
+    iProfileStatusCache.Close();
+    DestructVariant();
+    
+    //clear the accessory managers pointer to this session if it has one
+    iAccMan.ClearProfileNotifySession(*this);
+    
+    //clear the servers reference to this session
+    Server().ClientClosed(*this);
+    }
+
+void CBTAccSession::CreateL()
+    {
+    TRACE_FUNC
+    //use CreateL instead of NewSessionL when using Server() to ensure the
+    //session has been created correctly and Server() returns a valid pointer
+    Server().ClientOpened(*this);
+    }
+
+void CBTAccSession::ConnectCompleted(TInt aErr, TInt aProfile, const RArray<TBTDevAddr>* aConflicts)
+    {
+    TRACE_FUNC
+    if (iConnectMsg.Handle())
+        {
+        TRACE_INFO((_L("CBTAccSession::ConnectCompleted err %d"), aErr))
+        if (aConflicts)
+            {
+            TBuf8<KBTDevAddrSize * 2> buf;
+            TInt count = aConflicts->Count();
+            for (TInt i = 0; i < count; i++)
+                {
+                buf.Append((*aConflicts)[i].Des());
+                }
+            
+            if (buf.Length())
+                {
+                iConnectMsg.Write(1, buf);
+                }
+            }
+        else if (!aErr)
+            {
+            TPckgBuf<TInt> buf(aProfile);
+            iConnectMsg.Write(1, buf);
+            }
+        iConnectMsg.Complete(aErr);
+        }
+    }
+    
+void CBTAccSession::DisconnectCompleted(TInt aProfile, TInt aErr)
+    {
+    TRACE_FUNC
+    if (iDisconnectMsg.Handle())
+        {
+        TRACE_FUNC
+        if (!aErr)
+            {
+            TPckgBuf<TInt> buf(aProfile);
+            iDisconnectMsg.Write(1, buf);
+            }
+        iDisconnectMsg.Complete(aErr);
+        }
+    }
+
+void CBTAccSession::DisconnectAllCompleted(TInt aErr)
+    {
+    TRACE_FUNC
+    if (iDisconnectAllMsg.Handle())
+        {
+        TRACE_FUNC
+        TRACE_INFO((_L("ERR %d"), aErr))    
+        iDisconnectAllMsg.Complete(aErr);
+        }
+    }
+    
+// ---------------------------------------------------------
+// CBTAccSession::ConnectToAccessory
+// ---------------------------------------------------------
+void CBTAccSession::ConnectToAccessory(const RMessage2& aMessage)
+    {
+    TRACE_FUNC
+    if (iConnectMsg.Handle())
+        {
+        aMessage.Complete(KErrServerBusy);
+        }
+    else
+        {
+        TInt err;
+        TBTDevAddrPckgBuf pckg;
+        iConnectMsg = aMessage;
+        err = aMessage.Read(0, pckg);
+        if (!err)
+            {
+            iConnectingAddr = pckg();
+            TRAP(err, iAccMan.ConnectL(*this, pckg()));
+            }
+        if (err)
+            {
+            iConnectMsg.Complete(err);
+            }
+        }
+    }
+    
+// ---------------------------------------------------------
+// CBTAccSession::ConnectToAccessory
+// ---------------------------------------------------------
+void CBTAccSession::CancelConnectToAccessory()
+    {
+    TRACE_FUNC
+     if (iConnectMsg.Handle())
+        {
+        iAccMan.CancelConnect(iConnectingAddr);
+        iConnectMsg.Complete(KErrCancel);
+        }
+    }
+    
+// ---------------------------------------------------------
+// CBTAccSession::DisconnectAccessory
+// ---------------------------------------------------------
+void CBTAccSession::DisconnectAccessory(const RMessage2& aMessage)
+    {
+    TRACE_FUNC
+    if (iDisconnectMsg.Handle() || iDisconnectAllMsg.Handle())
+        {
+        aMessage.Complete(KErrServerBusy);
+        }
+    else
+        {
+        iDisconnectMsg = aMessage;
+        TBTDevAddrPckgBuf pckg;
+        TInt err = aMessage.Read(0, pckg);
+        if (!err)
+            {
+            TRAP(err, iAccMan.DisconnectL(*this, pckg()));
+            }
+        if (err)
+            {
+            iDisconnectMsg.Complete(err);
+            }
+        }
+    }
+
+void CBTAccSession::GetConnections(const RMessage2& aMessage)
+    {
+    TRACE_FUNC
+    TProfiles profile = static_cast<TProfiles>(aMessage.Int1());
+    RPointerArray<const TAccInfo> infos;
+    TInt ret = iAccMan.AccInfos(infos);
+    
+    if (ret == KErrNone)
+        {
+        RBuf8 buf;
+        
+        //get the number of connected accessories
+        TInt accessoryCount = infos.Count();
+        
+        //create a buffer the size of either the client side buffer or the
+        //maximum amount of addresses (number of connected accessories)
+        TInt min = Min(aMessage.GetDesMaxLength(0) / KBTDevAddrSize, accessoryCount);        
+        ret = buf.Create(min * KBTDevAddrSize);
+        
+        //if the buffer was created successfully
+        if (ret == KErrNone)
+            {
+            //iterate through the accessory info array and append the device
+            //addresses to the buffer
+            for (TInt i = 0; i < min; i++)
+                {
+                if (infos[i]->iConnProfiles & profile)
+                    {
+                    buf.Append(infos[i]->iAddr.Des());
+                    }
+                }
+            }
+        
+        //finished with the accessory info array
+        infos.Close();
+        
+        //if there is no error and the buffer has something in,
+        //write the buffer to the message
+        if (ret == KErrNone)
+            {
+            ret = aMessage.Write(0, buf);
+            
+            if (ret == KErrNone)
+                {
+                ret = accessoryCount;
+                }
+            }
+        }
+    
+    //complete the message with either the number of addresses (num of
+    //connected accessories) or a system-wide error code
+    aMessage.Complete(ret);
+    }
+
+void CBTAccSession::DisconnectAllGracefully(const RMessage2& aMessage)
+    {
+    TRACE_FUNC
+    if (iDisconnectMsg.Handle() || iDisconnectAllMsg.Handle())
+        {
+        aMessage.Complete(KErrServerBusy);
+        }
+    else
+        {
+        iDisconnectAllMsg = aMessage;
+        TRAPD(err, iAccMan.DisconnectAllL(*this));
+        if (err)
+            {
+            iDisconnectAllMsg.Complete(err);
+            }
+        }
+    }
+
+void CBTAccSession::NotifyProfileStatus(const RMessage2& aMessage)
+    {
+    TRACE_FUNC
+    iAccMan.SetProfileNotifySession(*this);    
+    if (iNotifyProfileMsg.Handle())
+        {
+        aMessage.Complete(KErrInUse);
+        }
+    else
+        {
+        if (iProfileStatusCache.Count())
+            {
+            TProfileStatusPckgBuf buf(iProfileStatusCache[0]);
+            TInt err = aMessage.Write(0, buf);
+            aMessage.Complete(err);
+            iProfileStatusCache.Remove(0);
+            }
+        else
+            {
+            iNotifyProfileMsg = aMessage;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CBTAccSession::GetBTAccInfo
+// ---------------------------------------------------------
+void CBTAccSession::GetInfoOfConnectedAcc( const RMessage2& aMessage )
+    {
+    TRACE_FUNC
+    TAccInfo info;
+    TPckg<TAccInfo> infoPckg(info);
+    TInt err = aMessage.Read(0, infoPckg);
+    if (!err)
+        {
+        const TAccInfo* infoptr = iAccMan.AccInfo(info.GetBDAddress());
+        if (infoptr)
+            {
+            TPtr8 ptr((TUint8*)infoptr, sizeof(TAccInfo), sizeof(TAccInfo));
+            err = aMessage.Write(0, ptr);
+            }
+        else
+            {
+            err = KErrNotFound;
+            }
+        }
+    aMessage.Complete(err);
+    }
+    
+void CBTAccSession::IsConnected(const RMessage2& aMessage)
+    {
+    TRACE_FUNC
+    TBTDevAddrPckgBuf pckg;
+    TInt err = aMessage.Read(0, pckg);
+    
+    if (err == KErrNone)
+        {
+        aMessage.Complete(iAccMan.ConnectionStatus4Client(pckg()));
+        }
+    else
+        {
+        aMessage.Complete(err);
+        }
+    }
+
+void CBTAccSession::NotifyClientNewProfile(TInt aProfile, const TBTDevAddr& aAddr)
+    {
+    TRACE_FUNC
+    TProfileStatus newp;
+    newp.iAddr = aAddr;
+    newp.iConnected = ETrue;
+    newp.iProfiles = aProfile;
+    if (iNotifyProfileMsg.Handle())
+        {
+        TProfileStatusPckgBuf buf(newp);
+        TInt err = iNotifyProfileMsg.Write(0, buf);
+        iNotifyProfileMsg.Complete(err);        
+        }
+    else
+        {
+        UpdateProfileStatusCache(newp);
+        }
+    }
+    
+void CBTAccSession::NotifyClientNoProfile(TInt aProfile, const TBTDevAddr& aAddr)
+    {
+    TRACE_FUNC
+    TProfileStatus newp;
+    newp.iAddr = aAddr;
+    newp.iConnected = EFalse;
+    newp.iProfiles = aProfile;
+    if (iNotifyProfileMsg.Handle())
+        {
+        TProfileStatusPckgBuf buf(newp);
+        TInt err = iNotifyProfileMsg.Write(0, buf);
+        iNotifyProfileMsg.Complete(err);        
+        }
+    else
+        {
+        UpdateProfileStatusCache(newp);
+        }
+    }
+
+// ---------------------------------------------------------
+// Server
+// Return a reference to CBTServer
+// ---------------------------------------------------------
+//
+CBTAccServer& CBTAccSession::Server()
+    {
+    return *static_cast<CBTAccServer*>(const_cast<CServer2*>(CSession2::Server()));
+    }
+
+// ---------------------------------------------------------
+// ServiceL
+// service a client request; test the opcode and then do
+// appropriate servicing
+// ---------------------------------------------------------
+//
+void CBTAccSession::ServiceL(const RMessage2& aMessage)
+    {
+    TRACE_FUNC
+    TRACE_INFO((_L("CBTAccSession::DispatchMessageL func %d"), aMessage.Function()))
+    switch (aMessage.Function())
+        {
+        case EBTAccSrvConnectToAccessory:
+            {
+            ConnectToAccessory(aMessage);
+            break;
+            }
+        case EBTAccSrvCancelConnectToAccessory:
+            {
+            CancelConnectToAccessory();
+            aMessage.Complete(KErrNone);
+            break;
+            }
+
+        case EBTAccSrvDisconnectAccessory:
+            {
+            DisconnectAccessory(aMessage);
+            break;
+            }
+        case EBTAccSrvGetConnections:
+            {
+            GetConnections(aMessage);
+            break;
+            }
+        case EBTAccSrvDisconnectAllGracefully:
+            {
+            DisconnectAllGracefully(aMessage);
+            break;
+            }
+        case EBTAccSrvNotifyConnectionStatus:
+            {
+            NotifyProfileStatus(aMessage);
+            break;
+            }
+        case EBTAccSrvCancelNotifyConnectionStatus:
+            {
+            if (iNotifyProfileMsg.Handle())
+                {
+                iNotifyProfileMsg.Complete(KErrCancel);
+                }
+            aMessage.Complete(KErrNone);
+            break;
+            }
+        case EBTAccSrvConnectionStatus:
+            {
+            IsConnected(aMessage);
+            break;
+            }
+        case EBTAccSrvGetInfoOfConnectedAcc:
+            {
+            GetInfoOfConnectedAcc(aMessage);
+            break;
+            }
+        case EBTAccSrvAudioToPhone:
+        case EBTAccSrvAudioToAccessory:
+        case EBTAccSrvCancelAudioToAccessory:
+            {
+            HandleAudio4DosRequest(aMessage);
+            break;
+            }
+        default:
+            {
+            PanicClient(aMessage, EBTAccBadRequest);
+            break;
+            }
+        }
+    }
+
+void CBTAccSession::UpdateProfileStatusCache(const TProfileStatus& aStatus)
+    {
+    TRACE_FUNC
+    TInt count = iProfileStatusCache.Count();
+    for (TInt i = 0; i < count; i++)
+        {
+        if (iProfileStatusCache[i].iAddr == aStatus.iAddr && 
+            iProfileStatusCache[i].iProfiles == aStatus.iProfiles)
+            {
+            iProfileStatusCache[i].iConnected = aStatus.iConnected;
+            return;
+            }
+        }
+    iProfileStatusCache.Append(aStatus);
+    }
+
+// End of File