bluetoothengine/bthid/bthidserver/src/bthidserver.cpp
changeset 0 f63038272f30
child 1 6a1fe72036e3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/bthid/bthidserver/src/bthidserver.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,1631 @@
+/*
+* 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 <s32file.h>
+#include <bt_sock.h>
+#include <sysutil.h>
+//#include <hal.h> // for checking the MachineUID. also link to hal.lib
+#include <e32std.h>
+//#include <btmanclient.h>
+#include <btnotif.h>
+#include "bthidserver.h"
+#include "bthidsession.h"
+#include "bthidclientsrv.h"
+#include "bthidconnection.h"
+#include "socketlistener.h"
+#include "bthidtypes.h"
+#include "bthiddevice.h"
+#include "hiddescriptorlist.h"
+#include "hiddescriptor.h"
+#include "bthidserver.pan"
+#include "debug.h"
+#include "debugconfig.h"
+#include "hidgeneric.h"
+#include "hidlayoutids.h"
+#include "bthidPsKey.h"
+
+
+#ifndef DBG
+#ifdef _DEBUG
+#define DBG(a) a
+#else
+#define DBG(a)
+#endif
+#endif
+
+//File store location
+_LIT(KFileStore,"C:\\private\\2001E301\\bthiddevices.dat");
+
+/**  PubSub key read and write policies */
+_LIT_SECURITY_POLICY_C2( KBTHIDPSKeyReadPolicy, 
+                          ECapabilityLocalServices, ECapabilityReadDeviceData );
+_LIT_SECURITY_POLICY_C2( KBTHIDPSKeyWritePolicy, 
+                          ECapabilityLocalServices, ECapabilityWriteDeviceData );
+
+// A version number to use when storing device information
+// Only for future proofing.
+const TInt KDataFileVersionNumber = 1;
+
+CBTHidServer::CBTHidServer() :
+    CGenericServer(CActive::EPriorityStandard)
+    {
+    // Implementation not required
+    }
+
+CBTHidServer::~CBTHidServer()
+    {
+    delete iShutDownTimer;
+
+    delete iControlListener;
+
+    delete iInterruptListener;
+
+    delete iBTConnIndex;
+
+    delete iMasterContIndex; // Causes deletion of iBTConnContainer
+
+    if (iTempInterrupt)
+        {
+        iTempInterrupt->Close();
+        delete iTempInterrupt;
+        }
+
+    if (iTempControl)
+        {
+        iTempControl->Close();
+        delete iTempControl;
+        }
+
+    iFs.Close();
+    iSocketServ.Close();
+
+    iReqs.ResetAndDestroy();
+    
+    delete iGenHID;
+    
+    RProperty::Delete( KPSUidBthidSrv, KBTMouseCursorState );
+    }
+
+CBTHidServer* CBTHidServer::NewL()
+    {
+    CBTHidServer* self = CBTHidServer::NewLC();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+CBTHidServer* CBTHidServer::NewLC()
+    {
+    CBTHidServer* self = new (ELeave) CBTHidServer;
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+    }
+
+const TInt KShutdownDelay = 5000000;
+
+void CBTHidServer::StartShutdownTimerIfNoSession()
+    {
+    if (!ConnectionCount()
+            && (!iShutDownTimer || !iShutDownTimer->IsActive()))
+        {
+        if (!iShutDownTimer)TRAP_IGNORE(iShutDownTimer = CPeriodic::NewL(CActive::EPriorityStandard));
+        if (iShutDownTimer)
+            iShutDownTimer->Start(KShutdownDelay, 0, TCallBack(
+                    CBTHidServer::TimerFired, this));
+            TRACE_FUNC
+        }
+    }
+
+TInt CBTHidServer::TimerFired(TAny* /*aThis*/)
+    {
+        TRACE_STATIC_FUNC
+    CActiveScheduler::Stop();
+    return KErrNone;
+    }
+
+void CBTHidServer::CancelShutdownTimer()
+    {
+        TRACE_FUNC
+    delete iShutDownTimer;
+    iShutDownTimer = NULL;
+    }
+
+void CBTHidServer::ConstructL()
+    {
+
+        TRACE_INFO(_L("CBTHidServer::ConstructL()..."));
+    iMasterContIndex = CObjectConIx::NewL();
+
+    iBTConnContainer = iMasterContIndex->CreateL();
+
+    iBTConnIndex = CObjectIx::NewL();
+
+        // Connect to the file server
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Connecting to file server"));
+    User::LeaveIfError(iFs.Connect());
+
+    // Make the data storage path (if it doesn't exist)
+    // If we can't create it, we can still make connections. They just won't
+    // persist.
+    iFs.MkDirAll(KFileStore);
+        // Connect to the socket server.
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Connecting to socket server"));
+    User::LeaveIfError(iSocketServ.Connect());
+
+    // Create initial sockets to accept a connection on the control
+    // and interrupt channels
+    iTempControl = new (ELeave) RSocket;
+    iTempInterrupt = new (ELeave) RSocket;
+
+    // Set the security required for incoming connections on the
+    // control and interrupt channels. This is handled in socket level now.
+
+    // Create Socket listeners for the control and interrupt channel
+    // ETrue, authorisation from user for incoming connection is asked
+    iControlListener = CSocketListener::NewL(iSocketServ, KL2CAPHidControl,
+            *this, ETrue);
+
+    //no authorisation needs to be asked,
+    //since it is asked during Control channel re-connection.
+    iInterruptListener = CSocketListener::NewL(iSocketServ,
+            KL2CAPHidInterrupt, *this, EFalse);
+
+        // Request to accept connections into the sockets just created
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): AcceptingConnections..."));
+    User::LeaveIfError(iControlListener->AcceptConnection(*iTempControl));
+    User::LeaveIfError(iInterruptListener->AcceptConnection(*iTempInterrupt));
+
+        // Create the generic HID:
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Creating Generic HID"));
+    iGenHID = CGenericHid::NewL(this);
+
+        // Load details of any virtually-cabled devices.
+        // Trap the error, but we can live with failure to load stored
+        // information. The file may be corrupt and we don't want this
+        // to prevent us using the application
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Loading virtually cabled devices"));
+    TRAPD( err, LoadVirtuallyCabledDevicesL(KFileStore) );
+    if (KErrNone != err)
+        {
+        err = err;
+            TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Loading virtually cabled devices FAILED"));
+        }
+
+    TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Starting the server"));
+
+    User::LeaveIfError( RProperty::Define( KPSUidBthidSrv,
+                                            KBTMouseCursorState,
+                                            RProperty::EInt,
+                                            KBTHIDPSKeyReadPolicy,
+                                            KBTHIDPSKeyWritePolicy) );
+
+    StartL(KBTHidSrvName);
+
+    iActiveState = EFalse;
+
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Server Started."));
+
+    }
+
+CSession2* CBTHidServer::NewSessionL(const TVersion& aVersion,
+        const RMessage2& /*aMessage*/) const
+    {
+    // check we're the right version
+    if (!User::QueryVersionSupported(TVersion(KBTHIDServMajorVersionNumber,
+            KBTHIDServMinorVersionNumber, KBTHIDServBuildVersionNumber),
+            aVersion))
+        {
+        User::Leave(KErrNotSupported);
+        }
+    const_cast<CBTHidServer*> (this)->CancelShutdownTimer();
+    // make new session
+    return CBTHidServerSession::NewL(*const_cast<CBTHidServer*> (this));
+    }
+
+void CBTHidServer::InformClientsOfStatusChange(
+        const CBTHidDevice& aDeviceDetails, TBTHidConnState aState)
+    {
+        TRACE_INFO( (_L("[BTHID]\tCBTHidServer::InformClientsOfStatusChange, state=%d"),aState) );
+    if (aState == EBTDeviceConnected || aState == EBTDeviceLinkRestored
+            || aState == EBTDeviceLinkLost || aState == EBTDeviceDisconnected)
+        {
+        iLastUsedAddr = aDeviceDetails.iAddress;
+        iActiveState = ETrue;
+        }
+    else
+        {
+        iActiveState = EFalse;
+        }
+    InformStatusChange(aDeviceDetails.iAddress, aState);
+    GlobalNotify(aDeviceDetails.iAddress, aState);
+    }
+
+void CBTHidServer::InformStatusChange(const TBTDevAddr& aAddress,
+        TBTHidConnState aState)
+    {
+        TRACE_INFO( (_L("[BTHID]\tCBTHidServer::InformStatusChange, state=%d"),aState) );
+    THIDStateUpdateBuf updateBuf;
+    THIDStateUpdate& update = updateBuf();
+
+    update.iDeviceAddress = aAddress;
+    update.iState = aState;
+
+    // Send to all clients
+    iSessionIter.SetToFirst();
+    for (;;)
+        {
+        CBTHidServerSession* session;
+        session = reinterpret_cast<CBTHidServerSession*> (iSessionIter++);
+        if (!session)
+            {
+            break;
+            }
+
+        session->InformStatusChange(updateBuf);
+        }
+    }
+
+void CBTHidServer::GlobalNotify(const TBTDevAddr& aDeviceAddr,
+        TBTHidConnState aState)
+    {
+    switch (aState)
+        {
+        case EBTDeviceLinkRestored:
+            {
+            HandleAsyncRequest(aDeviceAddr, EBTConnected);
+            break;
+            }
+
+        case EBTDeviceLinkLost:
+        case EBTDeviceDisconnected:
+        case EBTDeviceUnplugged:
+            {
+            HandleAsyncRequest(aDeviceAddr, EBTDisconnected);
+            break;
+            }
+        default:
+            //No need to bother
+            break;
+        }
+    }
+
+TInt CBTHidServer::HandleAsyncRequest(const TBTDevAddr& aDeviceAddr,
+        TInt aNote)
+    {
+      TRAPD(err, HandleAsyncRequestL(aDeviceAddr, aNote));
+      return err;
+    }
+
+void CBTHidServer::HandleAsyncRequestL(const TBTDevAddr& aDeviceAddr,
+        TInt aNote)
+    {
+    CBTHidNotifierHelper* notifier = CBTHidNotifierHelper::NewL(*this, aNote, aDeviceAddr);
+    CleanupStack::PushL(notifier);
+    
+    iReqs.AppendL(notifier);
+    CleanupStack::Pop(notifier);
+    
+    if (iReqs.Count() == 1) // only display our notifier if there's nothing already showing
+        {
+        notifier->Start();
+        }
+    }
+
+void CBTHidServer::NotifierRequestCompleted()
+    {
+    delete iReqs[0];
+    iReqs.Remove(0);
+
+    if (iReqs.Count())
+        {
+        iReqs[0]->Start();
+        }
+    }
+
+void CBTHidServer::GenericHIDConnectL(CBTHidConnection* aConnection,
+        TBool aStartDriver)
+    {
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::GenericHIDConnectL"));
+    CBTHidDevice& devDetails = aConnection->DeviceDetails();
+
+    // Search for the first report descriptor and give this
+    // to Generic HID
+    TBool foundRepDesc = EFalse;
+    TInt i = 0;
+    while ((i < devDetails.iDescList->DescriptorCount()) && (!foundRepDesc))
+        {
+        // Get the next descriptor.
+        const CHidDescriptor& desc =
+                (*(aConnection->DeviceDetails().iDescList))[i];
+
+        if (desc.DescriptorType() == CHidDescriptor::EReportDescriptor)
+            {
+            foundRepDesc = ETrue;
+            User::LeaveIfError(iGenHID->ConnectedL(aConnection->ConnID(),
+                    desc.RawData()));
+
+            // Try to start the driver if required.
+            if (aStartDriver)
+                {
+                User::LeaveIfError(iGenHID->DriverActive(
+                        aConnection->ConnID(), CHidTransport::EActive));
+                }
+            }
+
+        i++;
+        }
+
+    // If we didn't find a report descriptor, the device information is corrupt
+    if (!foundRepDesc)
+        {
+        User::Leave(KErrCorrupt);
+        }
+    }
+
+void CBTHidServer::IncrementSessions()
+    {
+    iSessionCount++;
+    CancelShutdownTimer();
+    }
+
+void CBTHidServer::DecrementSessions()
+    {
+    iSessionCount--;
+    __ASSERT_DEBUG(iSessionCount >= 0, PanicServer(EMainSchedulerError));
+
+    if (iSessionCount <= 0)
+        {
+        iSessionCount = 0;
+        StartShutdownTimerIfNoSession();
+        }
+    }
+
+TInt CBTHidServer::RunError(TInt aError)
+    {
+    if (aError == KErrBadDescriptor)
+        {
+        // A bad descriptor error implies a badly programmed client,
+        // so panic it;
+        // otherwise report the error to the client
+        PanicClient(Message(), EBadDescriptor);
+        }
+    else
+        {
+        Message().Complete(aError);
+        }
+
+    // The leave will result in an early return from CServer::RunL(), skipping
+    // the call to request another message. So do that now in order to keep the
+    // server running.
+    ReStart();
+
+    return KErrNone; // handled the error fully
+    }
+
+void CBTHidServer::PanicClient(const RMessage2& aMessage, TInt aPanic)
+    {
+        TRACE_INFO( (_L("[BTHID]\tCBTHidServer::PanicClient(%d)"), aPanic) );
+    aMessage.Panic(KBTHIDServer, aPanic);
+    }
+
+void CBTHidServer::PanicServer(TInt aPanic)
+    {
+        TRACE_INFO( (_L("[BTHID]\tCBTHidServer::PanicServer( %d )"), aPanic) );
+    User::Panic(KBTHIDServer, aPanic);
+    }
+
+void CBTHidServer::ShutdownListeners(TInt aError)
+    {
+        // Shutdown listeners and close accepting sockets
+        TRACE_INFO( (_L("[BTHID]\tCBTHidServer::ShutdownListeners(%d)"), aError) )
+
+    (void) aError;
+
+    iControlListener->Cancel();
+    iInterruptListener->Cancel();
+
+    if (iTempInterrupt)
+        {
+        iTempInterrupt->Close();
+        }
+
+    if (iTempControl)
+        {
+        iTempControl->Close();
+        }
+    }
+
+TUint CBTHidServer::ConnectionCount()
+    {
+    return iBTConnContainer->Count();
+    }
+
+CBTHidDevice& CBTHidServer::ConnectionDetailsL(TInt aConnID)
+    {
+    CBTHidConnection *connection = IdentifyConnectionL(aConnID);
+
+    return connection->DeviceDetails();
+    }
+
+TBTEngConnectionStatus CBTHidServer::ConnectStatus(const TBTDevAddr& aAddress)
+    {
+    TInt i = 0;
+    TBool foundItem = EFalse;
+    TBTEngConnectionStatus retVal = EBTEngNotConnected;
+    TInt BTConnectionObjCount = iBTConnContainer->Count();
+
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConnectStatus()"));
+    while ((i < BTConnectionObjCount) && (!foundItem))
+        {
+        CBTHidConnection *connection =
+                static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+
+        if (connection)
+            {
+            CBTHidDevice& devDetails = connection->DeviceDetails();
+
+            if (devDetails.iAddress == aAddress)
+                {
+                foundItem = ETrue;
+                TBTConnectionState HidConnectionStatus =
+                        connection->ConnectStatus();
+                if (EFirstConnection == HidConnectionStatus || EConnecting
+                        == HidConnectionStatus || EHIDReconnecting
+                        == HidConnectionStatus || EHostReconnecting
+                        == HidConnectionStatus)
+                    {
+                    retVal = EBTEngConnecting;
+                    }
+                if (EConnected == HidConnectionStatus)
+                    {
+                    retVal = EBTEngConnected;
+                    }
+                }
+            }
+
+        i++;
+        }
+
+    return retVal;
+    }
+
+TBool CBTHidServer::GetConnectionAddress(TDes8& aAddressBuf)
+    {
+    TInt i = 0;
+    TBool retVal = EFalse;
+    TInt BTConnectionObjCount = iBTConnContainer->Count();
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::IsAllowToConnect()"));
+    while ((i < BTConnectionObjCount))
+        {
+        CBTHidConnection *connection =
+                static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+
+        if (connection)
+            {
+            CBTHidDevice& devDetails = connection->DeviceDetails();
+            if (connection->IsConnected())
+                {
+                retVal = ETrue;
+                aAddressBuf.Append((devDetails.iAddress).Des());
+                if (aAddressBuf.Length() == KBTDevAddrSize * 2)
+                    break;
+                }
+            }
+        i++;
+        }
+
+    return retVal;
+    }
+
+TBool CBTHidServer::IsAllowToConnectFromServerSide(TUint aDeviceSubClass)
+    {
+    TInt i = 0;
+    TBool retVal = ETrue;
+    TInt BTConnectionObjCount = iBTConnContainer->Count();
+
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::IsAllowToConnectFromServerSide()"));
+    while ((i < BTConnectionObjCount) && retVal)
+        {
+        CBTHidConnection *connection =
+                static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+
+        if (connection)
+            {
+            CBTHidDevice& devDetails = connection->DeviceDetails();
+            TBTConnectionState HidConnectionStatus =
+                    connection->ConnectStatus();
+            if (connection->IsConnected() || HidConnectionStatus
+                    == EHIDReconnecting)
+                {
+                if ((IsKeyboard(aDeviceSubClass) && IsKeyboard(
+                        devDetails.iDeviceSubClass)) || (IsPointer(
+                        aDeviceSubClass) && IsPointer(
+                        devDetails.iDeviceSubClass)))
+                    {
+                    retVal = EFalse;
+                    iConflictAddr = devDetails.iAddress;
+                    }
+                }
+            }
+        i++;
+        }
+
+    return retVal;
+    }
+
+TBool CBTHidServer::IsKeyboard(TUint aDeviceSubClass)
+    {
+    TUint deviceSubClass = aDeviceSubClass;
+    TBool retVal = EFalse;
+    if ((deviceSubClass >> 2) & EMinorDevicePeripheralKeyboard)
+        {
+        retVal = ETrue;
+        }
+    return retVal;
+    }
+
+TBool CBTHidServer::IsPointer(TUint aDeviceSubClass)
+    {
+    TUint deviceSubClass = aDeviceSubClass;
+    TBool retVal = EFalse;
+    if ((deviceSubClass >> 2) & EMinorDevicePeripheralPointer)
+        {
+        retVal = ETrue;
+        }
+    return retVal;
+    }
+
+TBool CBTHidServer::IsAllowToConnectFromClientSide(TBTDevAddr aDevAddr)
+    {
+    TInt i = 0;
+    TBool retVal = ETrue;
+    TInt BTConnectionObjCount = iBTConnContainer->Count();
+
+    TUint deviceSubClass = GetDeviceSubClass(aDevAddr);
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::IsAllowToConnectFromClientSide()"));
+    while ((i < BTConnectionObjCount) && retVal)
+        {
+        CBTHidConnection *connection =
+                static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+
+        if (connection)
+            {
+            CBTHidDevice& devDetails = connection->DeviceDetails();
+            TBTConnectionState HidConnectionStatus =
+                    connection->ConnectStatus();
+            if (connection->IsConnected() || HidConnectionStatus
+                    == EConnecting)
+                {
+                if (devDetails.iAddress != aDevAddr)
+                    {
+                    if ((IsKeyboard(deviceSubClass) && IsKeyboard(
+                            devDetails.iDeviceSubClass)) || (IsPointer(
+                            deviceSubClass) && IsPointer(
+                            devDetails.iDeviceSubClass)))
+                        {
+                        retVal = EFalse;
+                        iConflictAddr = devDetails.iAddress;
+                        }
+                    }
+                }
+            }
+        i++;
+        }
+
+    return retVal;
+    }
+
+TUint CBTHidServer::GetDeviceSubClass(TBTDevAddr aDevAddr)
+    {
+    TInt i = 0;
+    TUint deviceSubClass = 0;
+    TInt BTConnectionObjCount = iBTConnContainer->Count();
+
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::GetMinorDeviceClass()"));
+    while (i < BTConnectionObjCount)
+        {
+        CBTHidConnection *connection =
+                static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+
+        if (connection)
+            {
+            CBTHidDevice& devDetails = connection->DeviceDetails();
+
+            if (devDetails.iAddress == aDevAddr)
+                {
+                deviceSubClass = devDetails.iDeviceSubClass;
+                }
+            }
+        i++;
+        }
+    return deviceSubClass;
+    }
+
+TBTDevAddr CBTHidServer::ConflictAddress()
+    {
+    return iConflictAddr;
+    }
+
+void CBTHidServer::CleanOldConnection(TInt aConnID)
+    {
+    TInt i = 0;
+    TBTDevAddr currentAddr;
+    TRACE_INFO( (_L("[BTHID]\tCBTHidServer::CleanOldConnection() aConnID[%d]"), aConnID) );
+    CBTHidConnection* connection =
+            static_cast<CBTHidConnection*>(iBTConnIndex->At(aConnID));
+    TRACE_INFO( (_L("[BTHID]\tCBTHidServer::CleanOldConnection() aConnID[%d]"), aConnID) );
+    __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
+    
+    if (connection)
+        {
+        TRACE_INFO( _L("[BTHID]\tCBTHidServer::CleanOldConnection() if ") );
+        CBTHidDevice& currentDetails = connection->DeviceDetails();
+        currentAddr = currentDetails.iAddress;
+        TRACE_INFO( _L("[BTHID]\tCBTHidServer::CleanOldConnection() if 1") );
+        while (i < iBTConnContainer->Count())
+            {
+            TRACE_INFO( (_L("[BTHID]\tCBTHidServer::CleanOldConnection() i = [%d]"), i) );
+            connection = static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+
+            if (connection)
+                {
+                CBTHidDevice& devDetails = connection->DeviceDetails();
+                if (devDetails.iAddress == currentAddr && !(connection->IsConnected()))
+                    {
+                    TRACE_INFO( _L("[BTHID]\tCBTHidServer::CleanOldConnection() if 2") );
+                    iGenHID->Disconnected(connection->ConnID());
+                    iBTConnIndex->Remove(connection->ConnID());
+                    }
+                }
+            i++;
+            }
+        }
+
+    return;
+    } 
+
+TInt CBTHidServer::NewConnectionL()
+    {
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::NewConnectionL"));
+    CBTHidConnection *connection = CBTHidConnection::NewLC(iSocketServ,
+            *this, EConnecting);
+    // Add to the connection container object.
+    iBTConnContainer->AddL(connection);
+    CleanupStack::Pop(); // connection
+
+    // Now add the object to the index to get an id.
+    // We can't let this just leave since we have already inserted the
+    // connection object into the container.
+    TInt id = 0;
+    TRAPD( res,
+            id = iBTConnIndex->AddL(connection);
+            connection->SetConnID(id);
+    )
+
+    if (res != KErrNone)
+        {
+        // Couldn't make an index entry.
+        // Close the connection object, causing it to be removed from the
+        // container
+        connection->Close();
+        User::Leave(res);
+        }
+
+    return id;
+    }
+
+void CBTHidServer::DoFirstConnectionL(TInt aConnID)
+    {
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::DoFirstConnectionL"));
+    CBTHidConnection *connection = IdentifyConnectionL(aConnID);
+
+    CBTHidDevice &devDetails = ConnectionDetailsL(aConnID);
+    DBG(TUint DeviceClass = devDetails.iDeviceSubClass;
+
+        DBG(RDebug::Print(_L("[BTHID]\tCBTHidServer::DoFirstConnectionL iDeviceSubClass  = %d"), DeviceClass));
+        )
+        
+    
+    
+    if (!IsAllowToConnectFromServerSide(devDetails.iDeviceSubClass))
+        {
+        User::Leave(KErrAlreadyExists);
+        }
+
+    connection->ConnectL();
+    }
+
+void CBTHidServer::DeleteNewConnection(TInt aConnID)
+    {
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::DeleteNewConnection"));
+    iBTConnIndex->Remove(aConnID);
+    }
+
+/*Asks the server to disconnect (virtual cable unplug) a device totally,
+ * remove the connection entry from the connection container.
+ */
+void CBTHidServer::CloseBluetoothConnection(const TBTDevAddr& aAddress)
+
+    {
+    TInt i = 0;
+    TBool foundItem = EFalse;
+
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::CloseBluetoothConnection"));
+    while ((i < iBTConnContainer->Count()) && (!foundItem))
+        {
+        CBTHidConnection *connection =
+                static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+
+        CBTHidDevice& devDetails = connection->DeviceDetails();
+
+        if (devDetails.iAddress == aAddress)
+            {
+            foundItem = ETrue;
+            // Inform the Generic HID of the disconnection.
+            iGenHID->Disconnected(connection->ConnID());
+
+            // Get it to disconnect if its connected.
+            connection->Disconnect();
+
+            // Delete the connection object.
+            iBTConnIndex->Remove(connection->ConnID());
+
+            // Update the stored devices, as we could have power off
+            // and no clean shutdown.
+            // Use the non-leaving version.
+            StoreVirtuallyCabledDevices(KFileStore);
+            }
+
+        i++;
+        }
+
+    }
+
+/*Asks the server to disconnect all the devices totally,
+ * remove the connection entries from the connection container.
+ */
+void CBTHidServer::CloseAllBluetoothConnection()
+    {
+    TInt i = 0;
+
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::CloseAllBluetoothConnection"));
+
+    while (i < iBTConnContainer->Count())
+        {
+        CBTHidConnection *connection =
+                static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+        if (connection)
+            {
+            if (connection->IsConnected())
+                {
+                // Inform the Generic HID of the disconnection.
+                iGenHID->Disconnected(connection->ConnID());
+
+                // Get it to disconnect if its connected.
+                connection->Disconnect();
+
+                // Delete the connection object.
+                iBTConnIndex->Remove(connection->ConnID());
+
+                // Update the stored devices, as we could have power off
+                // and no clean shutdown.
+                // Use the non-leaving version.
+                StoreVirtuallyCabledDevices(KFileStore);
+                }
+            }
+
+        i++;
+        }
+    }
+
+void CBTHidServer::DisconnectDeviceL(const TBTDevAddr& aAddress)
+    {
+    TInt i = 0;
+    TBool foundItem = EFalse;
+
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::DisconnectDeviceL"));
+    while ((i < iBTConnContainer->Count()) && (!foundItem))
+        {
+        CBTHidConnection *connection =
+                static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+
+        CBTHidDevice& devDetails = connection->DeviceDetails();
+
+        if (devDetails.iAddress == aAddress)
+            {
+            foundItem = ETrue;
+
+            // Drop the bluetooth connection.
+            connection->DropConnection();
+
+            // Stop the driver.
+            iGenHID->DriverActive(connection->ConnID(),
+                    CHidTransport::ESuspend);
+
+            InformClientsOfStatusChange(connection->DeviceDetails(),
+                    EBTDeviceDisconnected);
+            //Microsoft Keyboard & other "Unsecure" devices
+            CheckAndSetControlListenerSecurityL(
+                    connection->DeviceDetails().iUseSecurity);
+            }
+
+        i++;
+        }
+    }
+
+void CBTHidServer::DisconnectAllDeviceL()
+    {
+    TInt i = 0;
+
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::DisconnectAllDeviceL"));
+    while (i < iBTConnContainer->Count())
+        {
+        CBTHidConnection *connection =
+                static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+
+        if (connection)
+            {
+            if (connection->IsConnected())
+                {
+                CBTHidDevice& devDetails = connection->DeviceDetails();
+
+                // Drop the bluetooth connection.
+                connection->DropConnection();
+
+                // Stop the driver.
+                iGenHID->DriverActive(connection->ConnID(),
+                        CHidTransport::ESuspend);
+
+                InformClientsOfStatusChange(devDetails,
+                        EBTDeviceDisconnected);
+                //Microsoft Keyboard & other "Unsecure" devices
+                CheckAndSetControlListenerSecurityL(
+                        devDetails.iUseSecurity);
+                }
+
+            i++;
+            }
+        }
+    }
+
+void CBTHidServer::CheckAndSetControlListenerSecurityL(TBool aSec)
+    {
+
+        TRACE_INFO( (_L("[BTHID]\tCBTHidServer::CheckAndSetControlListenerSecurityL(%d)"), aSec) );
+
+    //Checking for Microsoft Keyboard & other "Unsecure" devices
+
+    if (!aSec) //Security is set on in Constructor of listener. This overrides that setting.
+        {
+        delete iControlListener;
+        iControlListener = NULL;
+        if (iTempControl)
+            iTempControl->Close();
+        iControlListener = CSocketListener::NewL(iSocketServ,
+                KL2CAPHidControl, *this, EFalse); //iAuthorisationFlag); We need authorisation, unless otherwise stated.
+        User::LeaveIfError(iControlListener->AcceptConnection(*iTempControl));
+        }
+
+    }
+
+// from MBTConnectionObserver
+void CBTHidServer::HandleControlData(TInt aConnID, const TDesC8& aBuffer)
+    {
+    iGenHID->DataIn(aConnID, CHidTransport::EHidChannelCtrl, aBuffer);
+    }
+
+void CBTHidServer::HandleCommandAck(TInt aConnID, TInt aStatus)
+    {
+    iGenHID->CommandResult(aConnID, aStatus);
+    }
+
+void CBTHidServer::HandleInterruptData(TInt aConnID, const TDesC8& aBuffer)
+    {
+    iGenHID->DataIn(aConnID, CHidTransport::EHidChannelInt, aBuffer);
+    }
+
+void CBTHidServer::FirstTimeConnectionComplete(TInt aConnID, TInt aStatus)
+    {
+        TRACE_INFO( (_L("[BTHID]\tCBTHidServer::FirstTimeConnectionComplete(%d)"), aStatus));
+    TInt error = aStatus;
+
+    CBTHidConnection* connection =
+            static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
+    __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
+
+    if (error == KErrNone)
+        {
+        TBool genHidConnected = EFalse;
+
+            TRAP( error,
+                    // Inform the Generic HID of the Connection
+                    GenericHIDConnectL(connection, ETrue);
+
+                    // Record that we got as far as informing the Generic HID.
+                    genHidConnected = ETrue;
+
+                    // Try to start monitoring the channels.
+                    connection->StartMonitoringChannelsL();
+            )
+
+        if (error != KErrNone)
+            {
+            // If we informed the Generic HID of the connection, then
+            // we must also disconnect.
+            if (genHidConnected)
+                {
+                iGenHID->Disconnected(aConnID);
+                }
+
+            // Delete the connection object.
+            iBTConnIndex->Remove(aConnID);
+            }
+        else
+            {
+            // Update the stored devices, as we could have power off
+            // and no clean shutdown.
+            // Use the non-leaving version.
+            TRACE_INFO( _L("[BTHID]\tCBTHidServer::FirstTimeConnectionComplete() before CleanOldConnection") );
+            CleanOldConnection(aConnID);
+            TRACE_INFO( _L("[BTHID]\tCBTHidServer::FirstTimeConnectionComplete() after CleanOldConnection") );
+            StoreVirtuallyCabledDevices(KFileStore);
+            }
+        }
+    else
+        {
+        iBTConnIndex->Remove(aConnID);
+        }
+
+    // Report the connection result to the sessions.
+    iSessionIter.SetToFirst();
+    for (;;)
+        {
+        CBTHidServerSession* session;
+        session = reinterpret_cast<CBTHidServerSession*> (iSessionIter++);
+        if (!session)
+            {
+            break;
+            }
+
+        session->InformConnectionResult(aConnID, error);
+        }
+    }
+
+void CBTHidServer::LinkLost(TInt aConnID)
+    {
+        TRACE_INFO( (_L("[BTHID]\tCBTHidServer::LinkLost(%d)"), aConnID));
+    // Stop the driver.
+    iGenHID->DriverActive(aConnID, CHidTransport::ESuspend);
+
+    CBTHidConnection* connection =
+            static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
+    __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
+
+    // Inform clients of the change in status of this connection.
+    InformClientsOfStatusChange(connection->DeviceDetails(),
+            EBTDeviceLinkLost);
+    }
+
+void CBTHidServer::LinkRestored(TInt aConnID)
+    {
+    CBTHidConnection* connection =
+            static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
+    __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
+
+    // Inform the Generic HID of the reconnection
+    TInt error = iGenHID->DriverActive(aConnID, CHidTransport::EActive);
+
+    // If there was no error, try to start monitoring the channels.
+    if (error == KErrNone)
+        {
+            // Try to start monitoring channels.
+            TRAP( error, connection->StartMonitoringChannelsL(); )
+        }
+
+    // Report new connection status.
+    if (error == KErrNone)
+        {
+        InformClientsOfStatusChange(connection->DeviceDetails(),
+                EBTDeviceLinkRestored);
+        }
+    else
+        {
+        InformClientsOfStatusChange(connection->DeviceDetails(),
+                EBTDeviceUnplugged);
+        // Inform the Generic HID of the disconnection.
+        iGenHID->Disconnected(aConnID);
+        // Delete the connection object.
+        iBTConnIndex->Remove(aConnID);
+
+        // Update the stored devices, as we could have power off
+        // and no clean shutdown.
+        // Use the non-leaving version.
+        StoreVirtuallyCabledDevices(KFileStore);
+        }
+    }
+
+void CBTHidServer::Disconnected(TInt aConnID)
+    {
+    CBTHidConnection *connection =
+            static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
+    __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
+
+    // Stop the driver.
+    iGenHID->DriverActive(aConnID, CHidTransport::ESuspend);
+
+    // Report new connection status.
+    InformClientsOfStatusChange(connection->DeviceDetails(),
+            EBTDeviceDisconnected);
+
+        //Check if no security is needed for listening socket
+        //Microsoft Keyboard & other "Unsecure" devices need this.
+
+        // possible leave is sign of severe problems in BT stack. So no reason to handle leave.
+        TRAP_IGNORE( CheckAndSetControlListenerSecurityL(connection->DeviceDetails().iUseSecurity) );
+
+    }
+
+void CBTHidServer::Unplugged(TInt aConnID)
+    {
+    CBTHidConnection *connection =
+            static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
+    __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
+
+    // Report new connection status.
+    InformClientsOfStatusChange(connection->DeviceDetails(),
+            EBTDeviceUnplugged);
+
+    // Inform the Generic HID of the disconnection.
+    iGenHID->Disconnected(aConnID);
+
+    iBTConnIndex->Remove(aConnID);
+
+    // Update the stored devices, as we could have power off
+    // and no clean shutdown.
+    // Use the non-leaving version.
+    StoreVirtuallyCabledDevices(KFileStore);
+    }
+
+//from MListenerObserver
+void CBTHidServer::SocketAccepted(TUint aPort, TInt aErrorCode)
+    {
+    TBTSockAddr sockAddr;
+    TBTDevAddr devAddr;
+
+        TRACE_INFO( (_L("[BTHID]\tCBTHidServer::SocketAccepted, port=%d, error code=%d"), aPort, aErrorCode) );
+
+    // Check error code
+    if (aErrorCode != KErrNone)
+        {
+        // If we do get an error there isn't much we can about it.
+        // Just tidy up.
+
+        ShutdownListeners(aErrorCode);
+        }
+    else
+        {
+        TInt i = 0;
+        TInt count = iBTConnContainer->Count();
+        TInt err = KErrNone;
+
+        // Check which port has accepted a connection
+        switch (aPort)
+            {
+            // The HID Control Channel
+            case KL2CAPHidControl:
+                // Get the BT address of the device that has connected
+                iTempControl->RemoteName(sockAddr);
+                devAddr = sockAddr.BTAddr();
+                if (IsAllowToConnectFromClientSide(devAddr))
+                    {
+                    while ((i < count) && (iTempControl))
+                        {
+                        CBTHidConnection
+                                * connection =
+                                        static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+                        __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
+                        connection->OfferControlSocket(devAddr, iTempControl);
+                        i++;
+                        }
+
+                    }
+                else
+                    {
+                    InformStatusChange(devAddr, EBTDeviceAnotherExist);
+                    }
+
+                // The next socket to accept into
+                if (iTempControl)
+                    {
+                    // Reuse this socket
+                    iTempControl->Close();
+                    err = KErrNone;
+                    }
+                else
+                    {
+                    // Socket ownership has been transferred so create a new
+                    // socket
+                    //TRAP( err, iTempControl = new (ELeave) RSocket; )
+                    iTempControl = new RSocket;
+                    }
+
+                // Created a socket to accept into so accept next connection
+                if (err == KErrNone)
+                    {
+                    err = iControlListener->AcceptConnection(*iTempControl);
+                    }
+
+                // If we failed to allocate a new RSocket or failed
+                // in the AcceptConnectionL call it means we can no longer
+                // accept connections from a device.
+                if (err != KErrNone)
+                    {
+                        TRACE_INFO(_L("[BTHID]\tCBTHidServer::SocketAccepted, control channel failed, shutdown listener"));
+                    ShutdownListeners(err);
+                    }
+
+                break;
+
+                // The HID Interrupt Channel
+            case KL2CAPHidInterrupt:
+                // Get the BT address of the device that has connected
+                iTempInterrupt->RemoteName(sockAddr);
+                devAddr = sockAddr.BTAddr();
+                if (IsAllowToConnectFromClientSide(devAddr))
+                    {
+                    while ((i < count) && (iTempInterrupt))
+                        {
+                        CBTHidConnection
+                                *connection =
+                                        static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+                        __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
+                        connection->OfferInterruptSocket(devAddr,
+                                iTempInterrupt);
+                        i++;
+                        }
+                    }
+                else
+                    {
+                    //Commented for avoiding display the same notes twice for same device
+                    //because of two channels(Control+Interrupt) has been rejected
+                    //InformStatusChange(devAddr, EBTDeviceAnotherExist);
+                    }
+
+                // The next socket to accept into
+                if (iTempInterrupt)
+                    {
+                    // Reuse this socket
+                    iTempInterrupt->Close();
+                    err = KErrNone;
+                    }
+                else
+                    {
+                    // Socket ownership has been transferred so create a new
+                    // socket
+                    //TRAP( err, iTempInterrupt = new (ELeave) RSocket; )
+                    iTempInterrupt = new RSocket;
+                    }
+
+                // Created a socket to accept into so accept next connection
+                if (err == KErrNone)
+                    {
+                    err = iInterruptListener->AcceptConnection(
+                            *iTempInterrupt);
+                    }
+
+                // If we failed to allocate a new RSocket or failed
+                // in the AcceptConnectionL call it means we can no longer
+                // accept connections from a device.
+                if (err != KErrNone)
+                    {
+                        TRACE_INFO(_L("[BTHID]\tCBTHidServer::SocketAccepted, interrupt channel failed, shutdown listener"));
+                    ShutdownListeners(err);
+                    }
+                break;
+
+            default:
+                PanicServer(EInvalidHandle);
+                break;
+            }
+        }
+
+    }
+
+//from MTransportLayer
+TUint CBTHidServer::CountryCodeL(TInt aConnID)
+    {
+    // Identify the connection object.
+    CBTHidConnection* conn = IdentifyConnectionL(aConnID);
+    // Retrieve its device details.
+    const CBTHidDevice& device = conn->DeviceDetails();
+
+    //return the country code
+    return device.iCountryCode;
+    }
+
+TUint CBTHidServer::VendorIdL(TInt aConnID)
+    {
+    // Identify the connection object.
+    CBTHidConnection* conn = IdentifyConnectionL(aConnID);
+    // Retrieve its device details.
+    const CBTHidDevice& device = conn->DeviceDetails();
+
+    //return the Vendor Id.
+    return device.iVendorID;
+    }
+
+TUint CBTHidServer::ProductIdL(TInt aConnID)
+    {
+    // Identify the connection object.
+    CBTHidConnection* conn = IdentifyConnectionL(aConnID);
+    // Retrieve its device details.
+    const CBTHidDevice& device = conn->DeviceDetails();
+
+    //return the Product Id.
+    return device.iProductID;
+    }
+
+void CBTHidServer::GetProtocolL(TInt aConnID, TUint16 /*aInterface*/)
+    {
+    CBTHidConnection *connection = IdentifyConnectionL(aConnID);
+
+    // Bluetooth HID only has one interface. We don't need the interface param.
+    connection->GetProtocolL();
+    }
+
+void CBTHidServer::SetProtocolL(TInt aConnID, TUint16 aValue, TUint16 /*aInterface*/)
+    {
+    CBTHidConnection *connection = IdentifyConnectionL(aConnID);
+
+    // Bluetooth HID only has one interface. We don't need the interface param.
+    connection->SetProtocolL(aValue);
+    }
+
+void CBTHidServer::GetReportL(TInt aConnID, TUint8 aReportType,
+        TUint8 aReportID, TUint16 /*aInterface*/, TUint16 aLength)
+    {
+    CBTHidConnection *connection = IdentifyConnectionL(aConnID);
+
+    // Bluetooth HID only has one interface. We don't need the interface param.
+    connection->GetReportL(aReportType, aReportID, aLength);
+    }
+
+void CBTHidServer::SetReportL(TInt aConnID, TUint8 aReportType,
+        TUint8 aReportID, TUint16 /*aInterface*/, const TDesC8& aReport)
+    {
+    CBTHidConnection *connection = IdentifyConnectionL(aConnID);
+
+    // Bluetooth HID only has one interface. We don't need the interface param
+    connection->SetReportL(aReportType, aReportID, aReport);
+    }
+
+void CBTHidServer::DataOutL(TInt aConnID, TUint8 aReportID,
+        TUint16 /*aInterface*/, const TDesC8& aReport)
+    {
+    CBTHidConnection *connection = IdentifyConnectionL(aConnID);
+
+    // Bluetooth HID only has one interface. We don't need the interface param
+    connection->DataOutL(aReportID, aReport); //we disregard DATA Input, DATA Feature and DATA Other
+    }
+
+void CBTHidServer::GetIdleL(TInt aConnID, TUint8 /*aReportID*/, TUint16 /*aInterface*/)
+    {
+    CBTHidConnection *connection = IdentifyConnectionL(aConnID);
+
+    // Bluetooth HID only has one interface. We don't need the interface param.
+    // Bluetooth HID doesn't specify Report ID.
+    connection->GetIdleL();
+    }
+
+void CBTHidServer::SetIdleL(TInt aConnID, TUint8 aDuration,
+        TUint8 /*aReportID*/, TUint16 /*aInterface*/)
+    {
+    CBTHidConnection *connection = IdentifyConnectionL(aConnID);
+
+    // Bluetooth HID only has one interface. We don't need the interface param.
+    // Bluetooth HID doesn't specify Report ID.
+    connection->SetIdleL(aDuration);
+    }
+
+CBTHidConnection* CBTHidServer::IdentifyConnectionL(TInt aConnID) const
+    {
+    CBTHidConnection *connection =
+            static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
+
+    if (!connection)
+        {
+        User::Leave(KErrNotFound);
+        }
+
+    return connection;
+    }
+
+void CBTHidServer::LoadVirtuallyCabledDevicesL(const TDesC& aStoreName)
+    {
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::LoadVirtuallyCabledDevicesL"));
+    // Create the parsed name and open the store
+    TParse parsedName;
+    User::LeaveIfError(iFs.Parse(aStoreName, parsedName));
+
+    CFileStore* store = CDirectFileStore::OpenLC(iFs, parsedName.FullName(),
+            EFileRead);
+
+    // Open the data stream inside the store
+    RStoreReadStream stream;
+    stream.OpenLC(*store, store->Root());
+
+    // Read the version number of the data file.
+    // Its not used in this version.
+    stream.ReadInt32L();
+
+    // Get the number of devices to load.
+    TInt count = stream.ReadInt32L();
+    TInt i;
+    for (i = 0; i < count; i++)
+        {
+        // Create the connection object. Ok to leave.
+        CBTHidConnection* connection = CBTHidConnection::NewLC(iSocketServ,
+                *this, ENotConnected);
+
+        stream >> connection->DeviceDetails();
+        // Check if no security is needed, then override earlier Control listener with unsecure one.
+        // This is needed for Microsoft Keyboard fix.
+        CheckAndSetControlListenerSecurityL(
+                connection->DeviceDetails().iUseSecurity);
+
+        // Add to the connection container object.
+        iBTConnContainer->AddL(connection);
+        CleanupStack::Pop(); // connection
+
+        // We can't let this just leave since we have already inserted the
+        // connection object into the container.
+        TBool connectionIndexed = EFalse;
+        TRAPD( res,
+                // Now add the object to the index to get an id.
+                TInt id = iBTConnIndex->AddL(connection);
+                connection->SetConnID(id);
+                connectionIndexed = ETrue;
+                connection->ReconnectL();
+
+                // Inform the Generic HID of the connection, but don't
+                // start the driver yet. This will be done in LinkRestored.
+                GenericHIDConnectL(connection, EFalse);
+        )
+
+        if (res != KErrNone)
+            {
+            if (connectionIndexed)
+                {
+                // Connection object was added to the index, but reconnection
+                // failed.
+                iBTConnIndex->Remove(connection->ConnID());
+                }
+            else
+                {
+                // Couldn't make an index entry.
+                // Close the connection object, causing it to be removed from
+                // the container.
+                connection->Close();
+                }
+            }
+        }
+
+    // Delete all the remaining stuff on the cleanup stack
+    // (store and stream)
+    CleanupStack::PopAndDestroy(2);
+    }
+
+void CBTHidServer::StoreVirtuallyCabledDevicesL(const TDesC& aStoreName)
+    {
+        TRACE_INFO(_L("[BTHID]\tCBTHidServer::StoreVirtuallyCabledDevicesL"));
+    // Parse the filestore name into a usable version.
+    TParse parsedName;
+    User::LeaveIfError(iFs.Parse(aStoreName, parsedName));
+
+    // Count the number of devices that we will need to store.
+    // Also count the accumulated disk size require for each one.
+    TInt numVirtuallyCabled = 0;
+    TInt requiredDiskSize = 0;
+
+    TInt i;
+
+    for (i = 0; i < iBTConnContainer->Count(); i++)
+        {
+        CBTHidConnection *connection =
+                static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+
+        if (connection)
+            {
+            CBTHidDevice &device = connection->DeviceDetails();
+            if (device.iVirtuallyCabled)
+                {
+                numVirtuallyCabled++;
+                // Increase the required size.
+                requiredDiskSize += device.DiskSize();
+                }
+            }
+        }
+
+    // Check for required disk size
+    // NOTE !! Be careful when changing functionality in here
+
+    // We have the number of bytes required to store all the device objects
+    // we want to store
+
+    // First thing written will be the file version which is 4 bytes
+    // Then the number of virtually cabled devices which is 4 bytes
+    requiredDiskSize += 8;
+
+        TRACE_INFO( (_L("[BTHID]\tCBTHidServer::StoreVirtuallyCabledDevicesL: Required disk size %d bytes"),
+                        requiredDiskSize) );
+    // Now check that the required number of bytes will not take us into
+    // the critical disk space area.
+    if (SysUtil::DiskSpaceBelowCriticalLevelL(&iFs, requiredDiskSize, EDriveC))
+        {
+        User::Leave(KErrDiskFull);
+        }
+
+    // Start the write for real.
+
+    CFileStore* store = CDirectFileStore::ReplaceLC(iFs,
+            parsedName.FullName(), EFileWrite);
+    store->SetTypeL(KDirectFileStoreLayoutUid);
+
+    // Create the stream
+    RStoreWriteStream stream;
+    TStreamId id = stream.CreateLC(*store);
+
+    // Write the version number of the data file
+    stream.WriteInt32L(KDataFileVersionNumber);
+
+    // Write the number of devices we are going to store.
+    stream.WriteInt32L(numVirtuallyCabled);
+
+    // Externalise each device object that is virtually cabled.
+    for (i = 0; i < iBTConnContainer->Count(); i++)
+        {
+        CBTHidConnection *connection =
+                static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
+
+        if (connection)
+            {
+            CBTHidDevice &device = connection->DeviceDetails();
+            if (device.iVirtuallyCabled)
+                {
+                stream << device;
+                }
+            }
+
+        }
+
+    // Commit the changes to the stream
+    stream.CommitL();
+    CleanupStack::PopAndDestroy();
+
+    // Set the stream in the store and commit the store
+    store->SetRootL(id);
+    store->CommitL();
+    CleanupStack::PopAndDestroy();
+    }
+
+void CBTHidServer::StoreVirtuallyCabledDevices(const TDesC& aStoreName)
+    {
+        TRAP_IGNORE( StoreVirtuallyCabledDevicesL(aStoreName);)
+    }
+
+void RunServerL()
+    {
+        TRACE_FUNC_ENTRY
+    User::RenameThread(KBTHidSrvName);
+    // Create and install the active scheduler for this thread.
+    CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
+    CleanupStack::PushL(scheduler);
+    CActiveScheduler::Install(scheduler);
+    // create the server (leave it on the cleanup stack)
+    CBTHidServer* btHidServer = CBTHidServer::NewLC();
+    // Initialisation complete, now signal the client
+    RProcess::Rendezvous(KErrNone);
+        // The server is not up and running.
+        TRACE_INFO( ( _L( "[BTHID]\t BTHID server now up and running" ) ) )
+    // The active scheduler runs during the lifetime of this thread.
+    CActiveScheduler::Start();
+    // Cleanup the server and scheduler.
+    CleanupStack::PopAndDestroy(btHidServer);
+    CleanupStack::PopAndDestroy(scheduler);
+        TRACE_FUNC_EXIT
+    }
+
+GLDEF_C TInt E32Main()
+    {
+    __UHEAP_MARK;
+        TRACE_FUNC_ENTRY
+    CTrapCleanup* cleanup = CTrapCleanup::New();
+    TInt err = KErrNoMemory;
+    if (cleanup)
+        {
+            TRAP( err, RunServerL() );
+        delete cleanup;
+        }
+    __UHEAP_MARKEND;
+    return err;
+    }
+
+// CBTHidNotifierHelper
+
+CBTHidNotifierHelper* CBTHidNotifierHelper::NewL(CBTHidServer& aHidServer, TInt aNote, const TBTDevAddr& aDeviceAddr)
+    { 
+    CBTHidNotifierHelper* self = new(ELeave) CBTHidNotifierHelper(aHidServer, aNote, aDeviceAddr);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+CBTHidNotifierHelper::~CBTHidNotifierHelper()
+    {
+    Cancel();
+    iNotifier.Close();
+    }   
+
+void CBTHidNotifierHelper::Start()
+    {   
+    TRACE_INFO(_L("CBTHidNotifierHelper::Start()..."));
+    
+    // Simple async handling
+    iNotifier.StartNotifierAndGetResponse(iStatus,
+                    KBTGenericInfoNotifierUid, iGenericInfoNotifierType,
+                    iNoResult);
+    
+    // assert object is not already active
+    __ASSERT_DEBUG(!IsActive(), CBTHidServer::PanicServer(ENotifierAlreadyActive));
+    
+    SetActive();
+    }           
+
+void CBTHidNotifierHelper::DoCancel()
+    {
+    TRACE_INFO(_L("CBTHidNotifierHelper::DoCancel()..."));
+    
+    iNotifier.CancelNotifier(KBTGenericInfoNotifierUid);
+    }
+
+CBTHidNotifierHelper::CBTHidNotifierHelper(CBTHidServer& aHidServer, TInt aNote, const TBTDevAddr& aDeviceAddr)
+    : CActive(CActive::EPriorityStandard),
+    iHidServer(aHidServer)
+    {
+    TRACE_INFO(_L("CBTHidNotifierHelper::CBTHidNotifierHelper()..."));
+    
+    iGenericInfoNotifierType().iMessageType = (TBTGenericInfoNoteType) aNote;
+    iGenericInfoNotifierType().iRemoteAddr.Copy(aDeviceAddr.Des());
+    
+    CActiveScheduler::Add(this);
+    }
+    
+void CBTHidNotifierHelper::ConstructL()
+    {
+    TRACE_INFO(_L("CBTHidNotifierHelper::ConstructL()..."));
+    
+    User::LeaveIfError(iNotifier.Connect());
+    }
+    
+void CBTHidNotifierHelper::RunL()
+    {
+    TRACE_INFO(_L("CBTHidNotifierHelper::RunL()..."));
+    
+    iHidServer.NotifierRequestCompleted();
+    }