bluetoothengine/bthid/bthidserver/src/bthidserver.cpp
changeset 0 f63038272f30
child 1 6a1fe72036e3
equal deleted inserted replaced
-1:000000000000 0:f63038272f30
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  This is the implementation of application class
       
    15  *
       
    16 */
       
    17 
       
    18 #include <e32svr.h>
       
    19 #include <s32file.h>
       
    20 #include <bt_sock.h>
       
    21 #include <sysutil.h>
       
    22 //#include <hal.h> // for checking the MachineUID. also link to hal.lib
       
    23 #include <e32std.h>
       
    24 //#include <btmanclient.h>
       
    25 #include <btnotif.h>
       
    26 #include "bthidserver.h"
       
    27 #include "bthidsession.h"
       
    28 #include "bthidclientsrv.h"
       
    29 #include "bthidconnection.h"
       
    30 #include "socketlistener.h"
       
    31 #include "bthidtypes.h"
       
    32 #include "bthiddevice.h"
       
    33 #include "hiddescriptorlist.h"
       
    34 #include "hiddescriptor.h"
       
    35 #include "bthidserver.pan"
       
    36 #include "debug.h"
       
    37 #include "debugconfig.h"
       
    38 #include "hidgeneric.h"
       
    39 #include "hidlayoutids.h"
       
    40 #include "bthidPsKey.h"
       
    41 
       
    42 
       
    43 #ifndef DBG
       
    44 #ifdef _DEBUG
       
    45 #define DBG(a) a
       
    46 #else
       
    47 #define DBG(a)
       
    48 #endif
       
    49 #endif
       
    50 
       
    51 //File store location
       
    52 _LIT(KFileStore,"C:\\private\\2001E301\\bthiddevices.dat");
       
    53 
       
    54 /**  PubSub key read and write policies */
       
    55 _LIT_SECURITY_POLICY_C2( KBTHIDPSKeyReadPolicy, 
       
    56                           ECapabilityLocalServices, ECapabilityReadDeviceData );
       
    57 _LIT_SECURITY_POLICY_C2( KBTHIDPSKeyWritePolicy, 
       
    58                           ECapabilityLocalServices, ECapabilityWriteDeviceData );
       
    59 
       
    60 // A version number to use when storing device information
       
    61 // Only for future proofing.
       
    62 const TInt KDataFileVersionNumber = 1;
       
    63 
       
    64 CBTHidServer::CBTHidServer() :
       
    65     CGenericServer(CActive::EPriorityStandard)
       
    66     {
       
    67     // Implementation not required
       
    68     }
       
    69 
       
    70 CBTHidServer::~CBTHidServer()
       
    71     {
       
    72     delete iShutDownTimer;
       
    73 
       
    74     delete iControlListener;
       
    75 
       
    76     delete iInterruptListener;
       
    77 
       
    78     delete iBTConnIndex;
       
    79 
       
    80     delete iMasterContIndex; // Causes deletion of iBTConnContainer
       
    81 
       
    82     if (iTempInterrupt)
       
    83         {
       
    84         iTempInterrupt->Close();
       
    85         delete iTempInterrupt;
       
    86         }
       
    87 
       
    88     if (iTempControl)
       
    89         {
       
    90         iTempControl->Close();
       
    91         delete iTempControl;
       
    92         }
       
    93 
       
    94     iFs.Close();
       
    95     iSocketServ.Close();
       
    96 
       
    97     iReqs.ResetAndDestroy();
       
    98     
       
    99     delete iGenHID;
       
   100     
       
   101     RProperty::Delete( KPSUidBthidSrv, KBTMouseCursorState );
       
   102     }
       
   103 
       
   104 CBTHidServer* CBTHidServer::NewL()
       
   105     {
       
   106     CBTHidServer* self = CBTHidServer::NewLC();
       
   107     CleanupStack::Pop(self);
       
   108     return self;
       
   109     }
       
   110 
       
   111 CBTHidServer* CBTHidServer::NewLC()
       
   112     {
       
   113     CBTHidServer* self = new (ELeave) CBTHidServer;
       
   114     CleanupStack::PushL(self);
       
   115     self->ConstructL();
       
   116     return self;
       
   117     }
       
   118 
       
   119 const TInt KShutdownDelay = 5000000;
       
   120 
       
   121 void CBTHidServer::StartShutdownTimerIfNoSession()
       
   122     {
       
   123     if (!ConnectionCount()
       
   124             && (!iShutDownTimer || !iShutDownTimer->IsActive()))
       
   125         {
       
   126         if (!iShutDownTimer)TRAP_IGNORE(iShutDownTimer = CPeriodic::NewL(CActive::EPriorityStandard));
       
   127         if (iShutDownTimer)
       
   128             iShutDownTimer->Start(KShutdownDelay, 0, TCallBack(
       
   129                     CBTHidServer::TimerFired, this));
       
   130             TRACE_FUNC
       
   131         }
       
   132     }
       
   133 
       
   134 TInt CBTHidServer::TimerFired(TAny* /*aThis*/)
       
   135     {
       
   136         TRACE_STATIC_FUNC
       
   137     CActiveScheduler::Stop();
       
   138     return KErrNone;
       
   139     }
       
   140 
       
   141 void CBTHidServer::CancelShutdownTimer()
       
   142     {
       
   143         TRACE_FUNC
       
   144     delete iShutDownTimer;
       
   145     iShutDownTimer = NULL;
       
   146     }
       
   147 
       
   148 void CBTHidServer::ConstructL()
       
   149     {
       
   150 
       
   151         TRACE_INFO(_L("CBTHidServer::ConstructL()..."));
       
   152     iMasterContIndex = CObjectConIx::NewL();
       
   153 
       
   154     iBTConnContainer = iMasterContIndex->CreateL();
       
   155 
       
   156     iBTConnIndex = CObjectIx::NewL();
       
   157 
       
   158         // Connect to the file server
       
   159         TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Connecting to file server"));
       
   160     User::LeaveIfError(iFs.Connect());
       
   161 
       
   162     // Make the data storage path (if it doesn't exist)
       
   163     // If we can't create it, we can still make connections. They just won't
       
   164     // persist.
       
   165     iFs.MkDirAll(KFileStore);
       
   166         // Connect to the socket server.
       
   167         TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Connecting to socket server"));
       
   168     User::LeaveIfError(iSocketServ.Connect());
       
   169 
       
   170     // Create initial sockets to accept a connection on the control
       
   171     // and interrupt channels
       
   172     iTempControl = new (ELeave) RSocket;
       
   173     iTempInterrupt = new (ELeave) RSocket;
       
   174 
       
   175     // Set the security required for incoming connections on the
       
   176     // control and interrupt channels. This is handled in socket level now.
       
   177 
       
   178     // Create Socket listeners for the control and interrupt channel
       
   179     // ETrue, authorisation from user for incoming connection is asked
       
   180     iControlListener = CSocketListener::NewL(iSocketServ, KL2CAPHidControl,
       
   181             *this, ETrue);
       
   182 
       
   183     //no authorisation needs to be asked,
       
   184     //since it is asked during Control channel re-connection.
       
   185     iInterruptListener = CSocketListener::NewL(iSocketServ,
       
   186             KL2CAPHidInterrupt, *this, EFalse);
       
   187 
       
   188         // Request to accept connections into the sockets just created
       
   189         TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): AcceptingConnections..."));
       
   190     User::LeaveIfError(iControlListener->AcceptConnection(*iTempControl));
       
   191     User::LeaveIfError(iInterruptListener->AcceptConnection(*iTempInterrupt));
       
   192 
       
   193         // Create the generic HID:
       
   194         TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Creating Generic HID"));
       
   195     iGenHID = CGenericHid::NewL(this);
       
   196 
       
   197         // Load details of any virtually-cabled devices.
       
   198         // Trap the error, but we can live with failure to load stored
       
   199         // information. The file may be corrupt and we don't want this
       
   200         // to prevent us using the application
       
   201         TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Loading virtually cabled devices"));
       
   202     TRAPD( err, LoadVirtuallyCabledDevicesL(KFileStore) );
       
   203     if (KErrNone != err)
       
   204         {
       
   205         err = err;
       
   206             TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Loading virtually cabled devices FAILED"));
       
   207         }
       
   208 
       
   209     TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Starting the server"));
       
   210 
       
   211     User::LeaveIfError( RProperty::Define( KPSUidBthidSrv,
       
   212                                             KBTMouseCursorState,
       
   213                                             RProperty::EInt,
       
   214                                             KBTHIDPSKeyReadPolicy,
       
   215                                             KBTHIDPSKeyWritePolicy) );
       
   216 
       
   217     StartL(KBTHidSrvName);
       
   218 
       
   219     iActiveState = EFalse;
       
   220 
       
   221         TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConstructL(): Server Started."));
       
   222 
       
   223     }
       
   224 
       
   225 CSession2* CBTHidServer::NewSessionL(const TVersion& aVersion,
       
   226         const RMessage2& /*aMessage*/) const
       
   227     {
       
   228     // check we're the right version
       
   229     if (!User::QueryVersionSupported(TVersion(KBTHIDServMajorVersionNumber,
       
   230             KBTHIDServMinorVersionNumber, KBTHIDServBuildVersionNumber),
       
   231             aVersion))
       
   232         {
       
   233         User::Leave(KErrNotSupported);
       
   234         }
       
   235     const_cast<CBTHidServer*> (this)->CancelShutdownTimer();
       
   236     // make new session
       
   237     return CBTHidServerSession::NewL(*const_cast<CBTHidServer*> (this));
       
   238     }
       
   239 
       
   240 void CBTHidServer::InformClientsOfStatusChange(
       
   241         const CBTHidDevice& aDeviceDetails, TBTHidConnState aState)
       
   242     {
       
   243         TRACE_INFO( (_L("[BTHID]\tCBTHidServer::InformClientsOfStatusChange, state=%d"),aState) );
       
   244     if (aState == EBTDeviceConnected || aState == EBTDeviceLinkRestored
       
   245             || aState == EBTDeviceLinkLost || aState == EBTDeviceDisconnected)
       
   246         {
       
   247         iLastUsedAddr = aDeviceDetails.iAddress;
       
   248         iActiveState = ETrue;
       
   249         }
       
   250     else
       
   251         {
       
   252         iActiveState = EFalse;
       
   253         }
       
   254     InformStatusChange(aDeviceDetails.iAddress, aState);
       
   255     GlobalNotify(aDeviceDetails.iAddress, aState);
       
   256     }
       
   257 
       
   258 void CBTHidServer::InformStatusChange(const TBTDevAddr& aAddress,
       
   259         TBTHidConnState aState)
       
   260     {
       
   261         TRACE_INFO( (_L("[BTHID]\tCBTHidServer::InformStatusChange, state=%d"),aState) );
       
   262     THIDStateUpdateBuf updateBuf;
       
   263     THIDStateUpdate& update = updateBuf();
       
   264 
       
   265     update.iDeviceAddress = aAddress;
       
   266     update.iState = aState;
       
   267 
       
   268     // Send to all clients
       
   269     iSessionIter.SetToFirst();
       
   270     for (;;)
       
   271         {
       
   272         CBTHidServerSession* session;
       
   273         session = reinterpret_cast<CBTHidServerSession*> (iSessionIter++);
       
   274         if (!session)
       
   275             {
       
   276             break;
       
   277             }
       
   278 
       
   279         session->InformStatusChange(updateBuf);
       
   280         }
       
   281     }
       
   282 
       
   283 void CBTHidServer::GlobalNotify(const TBTDevAddr& aDeviceAddr,
       
   284         TBTHidConnState aState)
       
   285     {
       
   286     switch (aState)
       
   287         {
       
   288         case EBTDeviceLinkRestored:
       
   289             {
       
   290             HandleAsyncRequest(aDeviceAddr, EBTConnected);
       
   291             break;
       
   292             }
       
   293 
       
   294         case EBTDeviceLinkLost:
       
   295         case EBTDeviceDisconnected:
       
   296         case EBTDeviceUnplugged:
       
   297             {
       
   298             HandleAsyncRequest(aDeviceAddr, EBTDisconnected);
       
   299             break;
       
   300             }
       
   301         default:
       
   302             //No need to bother
       
   303             break;
       
   304         }
       
   305     }
       
   306 
       
   307 TInt CBTHidServer::HandleAsyncRequest(const TBTDevAddr& aDeviceAddr,
       
   308         TInt aNote)
       
   309     {
       
   310       TRAPD(err, HandleAsyncRequestL(aDeviceAddr, aNote));
       
   311       return err;
       
   312     }
       
   313 
       
   314 void CBTHidServer::HandleAsyncRequestL(const TBTDevAddr& aDeviceAddr,
       
   315         TInt aNote)
       
   316     {
       
   317     CBTHidNotifierHelper* notifier = CBTHidNotifierHelper::NewL(*this, aNote, aDeviceAddr);
       
   318     CleanupStack::PushL(notifier);
       
   319     
       
   320     iReqs.AppendL(notifier);
       
   321     CleanupStack::Pop(notifier);
       
   322     
       
   323     if (iReqs.Count() == 1) // only display our notifier if there's nothing already showing
       
   324         {
       
   325         notifier->Start();
       
   326         }
       
   327     }
       
   328 
       
   329 void CBTHidServer::NotifierRequestCompleted()
       
   330     {
       
   331     delete iReqs[0];
       
   332     iReqs.Remove(0);
       
   333 
       
   334     if (iReqs.Count())
       
   335         {
       
   336         iReqs[0]->Start();
       
   337         }
       
   338     }
       
   339 
       
   340 void CBTHidServer::GenericHIDConnectL(CBTHidConnection* aConnection,
       
   341         TBool aStartDriver)
       
   342     {
       
   343         TRACE_INFO(_L("[BTHID]\tCBTHidServer::GenericHIDConnectL"));
       
   344     CBTHidDevice& devDetails = aConnection->DeviceDetails();
       
   345 
       
   346     // Search for the first report descriptor and give this
       
   347     // to Generic HID
       
   348     TBool foundRepDesc = EFalse;
       
   349     TInt i = 0;
       
   350     while ((i < devDetails.iDescList->DescriptorCount()) && (!foundRepDesc))
       
   351         {
       
   352         // Get the next descriptor.
       
   353         const CHidDescriptor& desc =
       
   354                 (*(aConnection->DeviceDetails().iDescList))[i];
       
   355 
       
   356         if (desc.DescriptorType() == CHidDescriptor::EReportDescriptor)
       
   357             {
       
   358             foundRepDesc = ETrue;
       
   359             User::LeaveIfError(iGenHID->ConnectedL(aConnection->ConnID(),
       
   360                     desc.RawData()));
       
   361 
       
   362             // Try to start the driver if required.
       
   363             if (aStartDriver)
       
   364                 {
       
   365                 User::LeaveIfError(iGenHID->DriverActive(
       
   366                         aConnection->ConnID(), CHidTransport::EActive));
       
   367                 }
       
   368             }
       
   369 
       
   370         i++;
       
   371         }
       
   372 
       
   373     // If we didn't find a report descriptor, the device information is corrupt
       
   374     if (!foundRepDesc)
       
   375         {
       
   376         User::Leave(KErrCorrupt);
       
   377         }
       
   378     }
       
   379 
       
   380 void CBTHidServer::IncrementSessions()
       
   381     {
       
   382     iSessionCount++;
       
   383     CancelShutdownTimer();
       
   384     }
       
   385 
       
   386 void CBTHidServer::DecrementSessions()
       
   387     {
       
   388     iSessionCount--;
       
   389     __ASSERT_DEBUG(iSessionCount >= 0, PanicServer(EMainSchedulerError));
       
   390 
       
   391     if (iSessionCount <= 0)
       
   392         {
       
   393         iSessionCount = 0;
       
   394         StartShutdownTimerIfNoSession();
       
   395         }
       
   396     }
       
   397 
       
   398 TInt CBTHidServer::RunError(TInt aError)
       
   399     {
       
   400     if (aError == KErrBadDescriptor)
       
   401         {
       
   402         // A bad descriptor error implies a badly programmed client,
       
   403         // so panic it;
       
   404         // otherwise report the error to the client
       
   405         PanicClient(Message(), EBadDescriptor);
       
   406         }
       
   407     else
       
   408         {
       
   409         Message().Complete(aError);
       
   410         }
       
   411 
       
   412     // The leave will result in an early return from CServer::RunL(), skipping
       
   413     // the call to request another message. So do that now in order to keep the
       
   414     // server running.
       
   415     ReStart();
       
   416 
       
   417     return KErrNone; // handled the error fully
       
   418     }
       
   419 
       
   420 void CBTHidServer::PanicClient(const RMessage2& aMessage, TInt aPanic)
       
   421     {
       
   422         TRACE_INFO( (_L("[BTHID]\tCBTHidServer::PanicClient(%d)"), aPanic) );
       
   423     aMessage.Panic(KBTHIDServer, aPanic);
       
   424     }
       
   425 
       
   426 void CBTHidServer::PanicServer(TInt aPanic)
       
   427     {
       
   428         TRACE_INFO( (_L("[BTHID]\tCBTHidServer::PanicServer( %d )"), aPanic) );
       
   429     User::Panic(KBTHIDServer, aPanic);
       
   430     }
       
   431 
       
   432 void CBTHidServer::ShutdownListeners(TInt aError)
       
   433     {
       
   434         // Shutdown listeners and close accepting sockets
       
   435         TRACE_INFO( (_L("[BTHID]\tCBTHidServer::ShutdownListeners(%d)"), aError) )
       
   436 
       
   437     (void) aError;
       
   438 
       
   439     iControlListener->Cancel();
       
   440     iInterruptListener->Cancel();
       
   441 
       
   442     if (iTempInterrupt)
       
   443         {
       
   444         iTempInterrupt->Close();
       
   445         }
       
   446 
       
   447     if (iTempControl)
       
   448         {
       
   449         iTempControl->Close();
       
   450         }
       
   451     }
       
   452 
       
   453 TUint CBTHidServer::ConnectionCount()
       
   454     {
       
   455     return iBTConnContainer->Count();
       
   456     }
       
   457 
       
   458 CBTHidDevice& CBTHidServer::ConnectionDetailsL(TInt aConnID)
       
   459     {
       
   460     CBTHidConnection *connection = IdentifyConnectionL(aConnID);
       
   461 
       
   462     return connection->DeviceDetails();
       
   463     }
       
   464 
       
   465 TBTEngConnectionStatus CBTHidServer::ConnectStatus(const TBTDevAddr& aAddress)
       
   466     {
       
   467     TInt i = 0;
       
   468     TBool foundItem = EFalse;
       
   469     TBTEngConnectionStatus retVal = EBTEngNotConnected;
       
   470     TInt BTConnectionObjCount = iBTConnContainer->Count();
       
   471 
       
   472         TRACE_INFO(_L("[BTHID]\tCBTHidServer::ConnectStatus()"));
       
   473     while ((i < BTConnectionObjCount) && (!foundItem))
       
   474         {
       
   475         CBTHidConnection *connection =
       
   476                 static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
   477 
       
   478         if (connection)
       
   479             {
       
   480             CBTHidDevice& devDetails = connection->DeviceDetails();
       
   481 
       
   482             if (devDetails.iAddress == aAddress)
       
   483                 {
       
   484                 foundItem = ETrue;
       
   485                 TBTConnectionState HidConnectionStatus =
       
   486                         connection->ConnectStatus();
       
   487                 if (EFirstConnection == HidConnectionStatus || EConnecting
       
   488                         == HidConnectionStatus || EHIDReconnecting
       
   489                         == HidConnectionStatus || EHostReconnecting
       
   490                         == HidConnectionStatus)
       
   491                     {
       
   492                     retVal = EBTEngConnecting;
       
   493                     }
       
   494                 if (EConnected == HidConnectionStatus)
       
   495                     {
       
   496                     retVal = EBTEngConnected;
       
   497                     }
       
   498                 }
       
   499             }
       
   500 
       
   501         i++;
       
   502         }
       
   503 
       
   504     return retVal;
       
   505     }
       
   506 
       
   507 TBool CBTHidServer::GetConnectionAddress(TDes8& aAddressBuf)
       
   508     {
       
   509     TInt i = 0;
       
   510     TBool retVal = EFalse;
       
   511     TInt BTConnectionObjCount = iBTConnContainer->Count();
       
   512         TRACE_INFO(_L("[BTHID]\tCBTHidServer::IsAllowToConnect()"));
       
   513     while ((i < BTConnectionObjCount))
       
   514         {
       
   515         CBTHidConnection *connection =
       
   516                 static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
   517 
       
   518         if (connection)
       
   519             {
       
   520             CBTHidDevice& devDetails = connection->DeviceDetails();
       
   521             if (connection->IsConnected())
       
   522                 {
       
   523                 retVal = ETrue;
       
   524                 aAddressBuf.Append((devDetails.iAddress).Des());
       
   525                 if (aAddressBuf.Length() == KBTDevAddrSize * 2)
       
   526                     break;
       
   527                 }
       
   528             }
       
   529         i++;
       
   530         }
       
   531 
       
   532     return retVal;
       
   533     }
       
   534 
       
   535 TBool CBTHidServer::IsAllowToConnectFromServerSide(TUint aDeviceSubClass)
       
   536     {
       
   537     TInt i = 0;
       
   538     TBool retVal = ETrue;
       
   539     TInt BTConnectionObjCount = iBTConnContainer->Count();
       
   540 
       
   541         TRACE_INFO(_L("[BTHID]\tCBTHidServer::IsAllowToConnectFromServerSide()"));
       
   542     while ((i < BTConnectionObjCount) && retVal)
       
   543         {
       
   544         CBTHidConnection *connection =
       
   545                 static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
   546 
       
   547         if (connection)
       
   548             {
       
   549             CBTHidDevice& devDetails = connection->DeviceDetails();
       
   550             TBTConnectionState HidConnectionStatus =
       
   551                     connection->ConnectStatus();
       
   552             if (connection->IsConnected() || HidConnectionStatus
       
   553                     == EHIDReconnecting)
       
   554                 {
       
   555                 if ((IsKeyboard(aDeviceSubClass) && IsKeyboard(
       
   556                         devDetails.iDeviceSubClass)) || (IsPointer(
       
   557                         aDeviceSubClass) && IsPointer(
       
   558                         devDetails.iDeviceSubClass)))
       
   559                     {
       
   560                     retVal = EFalse;
       
   561                     iConflictAddr = devDetails.iAddress;
       
   562                     }
       
   563                 }
       
   564             }
       
   565         i++;
       
   566         }
       
   567 
       
   568     return retVal;
       
   569     }
       
   570 
       
   571 TBool CBTHidServer::IsKeyboard(TUint aDeviceSubClass)
       
   572     {
       
   573     TUint deviceSubClass = aDeviceSubClass;
       
   574     TBool retVal = EFalse;
       
   575     if ((deviceSubClass >> 2) & EMinorDevicePeripheralKeyboard)
       
   576         {
       
   577         retVal = ETrue;
       
   578         }
       
   579     return retVal;
       
   580     }
       
   581 
       
   582 TBool CBTHidServer::IsPointer(TUint aDeviceSubClass)
       
   583     {
       
   584     TUint deviceSubClass = aDeviceSubClass;
       
   585     TBool retVal = EFalse;
       
   586     if ((deviceSubClass >> 2) & EMinorDevicePeripheralPointer)
       
   587         {
       
   588         retVal = ETrue;
       
   589         }
       
   590     return retVal;
       
   591     }
       
   592 
       
   593 TBool CBTHidServer::IsAllowToConnectFromClientSide(TBTDevAddr aDevAddr)
       
   594     {
       
   595     TInt i = 0;
       
   596     TBool retVal = ETrue;
       
   597     TInt BTConnectionObjCount = iBTConnContainer->Count();
       
   598 
       
   599     TUint deviceSubClass = GetDeviceSubClass(aDevAddr);
       
   600         TRACE_INFO(_L("[BTHID]\tCBTHidServer::IsAllowToConnectFromClientSide()"));
       
   601     while ((i < BTConnectionObjCount) && retVal)
       
   602         {
       
   603         CBTHidConnection *connection =
       
   604                 static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
   605 
       
   606         if (connection)
       
   607             {
       
   608             CBTHidDevice& devDetails = connection->DeviceDetails();
       
   609             TBTConnectionState HidConnectionStatus =
       
   610                     connection->ConnectStatus();
       
   611             if (connection->IsConnected() || HidConnectionStatus
       
   612                     == EConnecting)
       
   613                 {
       
   614                 if (devDetails.iAddress != aDevAddr)
       
   615                     {
       
   616                     if ((IsKeyboard(deviceSubClass) && IsKeyboard(
       
   617                             devDetails.iDeviceSubClass)) || (IsPointer(
       
   618                             deviceSubClass) && IsPointer(
       
   619                             devDetails.iDeviceSubClass)))
       
   620                         {
       
   621                         retVal = EFalse;
       
   622                         iConflictAddr = devDetails.iAddress;
       
   623                         }
       
   624                     }
       
   625                 }
       
   626             }
       
   627         i++;
       
   628         }
       
   629 
       
   630     return retVal;
       
   631     }
       
   632 
       
   633 TUint CBTHidServer::GetDeviceSubClass(TBTDevAddr aDevAddr)
       
   634     {
       
   635     TInt i = 0;
       
   636     TUint deviceSubClass = 0;
       
   637     TInt BTConnectionObjCount = iBTConnContainer->Count();
       
   638 
       
   639         TRACE_INFO(_L("[BTHID]\tCBTHidServer::GetMinorDeviceClass()"));
       
   640     while (i < BTConnectionObjCount)
       
   641         {
       
   642         CBTHidConnection *connection =
       
   643                 static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
   644 
       
   645         if (connection)
       
   646             {
       
   647             CBTHidDevice& devDetails = connection->DeviceDetails();
       
   648 
       
   649             if (devDetails.iAddress == aDevAddr)
       
   650                 {
       
   651                 deviceSubClass = devDetails.iDeviceSubClass;
       
   652                 }
       
   653             }
       
   654         i++;
       
   655         }
       
   656     return deviceSubClass;
       
   657     }
       
   658 
       
   659 TBTDevAddr CBTHidServer::ConflictAddress()
       
   660     {
       
   661     return iConflictAddr;
       
   662     }
       
   663 
       
   664 void CBTHidServer::CleanOldConnection(TInt aConnID)
       
   665     {
       
   666     TInt i = 0;
       
   667     TBTDevAddr currentAddr;
       
   668     TRACE_INFO( (_L("[BTHID]\tCBTHidServer::CleanOldConnection() aConnID[%d]"), aConnID) );
       
   669     CBTHidConnection* connection =
       
   670             static_cast<CBTHidConnection*>(iBTConnIndex->At(aConnID));
       
   671     TRACE_INFO( (_L("[BTHID]\tCBTHidServer::CleanOldConnection() aConnID[%d]"), aConnID) );
       
   672     __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
       
   673     
       
   674     if (connection)
       
   675         {
       
   676         TRACE_INFO( _L("[BTHID]\tCBTHidServer::CleanOldConnection() if ") );
       
   677         CBTHidDevice& currentDetails = connection->DeviceDetails();
       
   678         currentAddr = currentDetails.iAddress;
       
   679         TRACE_INFO( _L("[BTHID]\tCBTHidServer::CleanOldConnection() if 1") );
       
   680         while (i < iBTConnContainer->Count())
       
   681             {
       
   682             TRACE_INFO( (_L("[BTHID]\tCBTHidServer::CleanOldConnection() i = [%d]"), i) );
       
   683             connection = static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
   684 
       
   685             if (connection)
       
   686                 {
       
   687                 CBTHidDevice& devDetails = connection->DeviceDetails();
       
   688                 if (devDetails.iAddress == currentAddr && !(connection->IsConnected()))
       
   689                     {
       
   690                     TRACE_INFO( _L("[BTHID]\tCBTHidServer::CleanOldConnection() if 2") );
       
   691                     iGenHID->Disconnected(connection->ConnID());
       
   692                     iBTConnIndex->Remove(connection->ConnID());
       
   693                     }
       
   694                 }
       
   695             i++;
       
   696             }
       
   697         }
       
   698 
       
   699     return;
       
   700     } 
       
   701 
       
   702 TInt CBTHidServer::NewConnectionL()
       
   703     {
       
   704         TRACE_INFO(_L("[BTHID]\tCBTHidServer::NewConnectionL"));
       
   705     CBTHidConnection *connection = CBTHidConnection::NewLC(iSocketServ,
       
   706             *this, EConnecting);
       
   707     // Add to the connection container object.
       
   708     iBTConnContainer->AddL(connection);
       
   709     CleanupStack::Pop(); // connection
       
   710 
       
   711     // Now add the object to the index to get an id.
       
   712     // We can't let this just leave since we have already inserted the
       
   713     // connection object into the container.
       
   714     TInt id = 0;
       
   715     TRAPD( res,
       
   716             id = iBTConnIndex->AddL(connection);
       
   717             connection->SetConnID(id);
       
   718     )
       
   719 
       
   720     if (res != KErrNone)
       
   721         {
       
   722         // Couldn't make an index entry.
       
   723         // Close the connection object, causing it to be removed from the
       
   724         // container
       
   725         connection->Close();
       
   726         User::Leave(res);
       
   727         }
       
   728 
       
   729     return id;
       
   730     }
       
   731 
       
   732 void CBTHidServer::DoFirstConnectionL(TInt aConnID)
       
   733     {
       
   734         TRACE_INFO(_L("[BTHID]\tCBTHidServer::DoFirstConnectionL"));
       
   735     CBTHidConnection *connection = IdentifyConnectionL(aConnID);
       
   736 
       
   737     CBTHidDevice &devDetails = ConnectionDetailsL(aConnID);
       
   738     DBG(TUint DeviceClass = devDetails.iDeviceSubClass;
       
   739 
       
   740         DBG(RDebug::Print(_L("[BTHID]\tCBTHidServer::DoFirstConnectionL iDeviceSubClass  = %d"), DeviceClass));
       
   741         )
       
   742         
       
   743     
       
   744     
       
   745     if (!IsAllowToConnectFromServerSide(devDetails.iDeviceSubClass))
       
   746         {
       
   747         User::Leave(KErrAlreadyExists);
       
   748         }
       
   749 
       
   750     connection->ConnectL();
       
   751     }
       
   752 
       
   753 void CBTHidServer::DeleteNewConnection(TInt aConnID)
       
   754     {
       
   755         TRACE_INFO(_L("[BTHID]\tCBTHidServer::DeleteNewConnection"));
       
   756     iBTConnIndex->Remove(aConnID);
       
   757     }
       
   758 
       
   759 /*Asks the server to disconnect (virtual cable unplug) a device totally,
       
   760  * remove the connection entry from the connection container.
       
   761  */
       
   762 void CBTHidServer::CloseBluetoothConnection(const TBTDevAddr& aAddress)
       
   763 
       
   764     {
       
   765     TInt i = 0;
       
   766     TBool foundItem = EFalse;
       
   767 
       
   768         TRACE_INFO(_L("[BTHID]\tCBTHidServer::CloseBluetoothConnection"));
       
   769     while ((i < iBTConnContainer->Count()) && (!foundItem))
       
   770         {
       
   771         CBTHidConnection *connection =
       
   772                 static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
   773 
       
   774         CBTHidDevice& devDetails = connection->DeviceDetails();
       
   775 
       
   776         if (devDetails.iAddress == aAddress)
       
   777             {
       
   778             foundItem = ETrue;
       
   779             // Inform the Generic HID of the disconnection.
       
   780             iGenHID->Disconnected(connection->ConnID());
       
   781 
       
   782             // Get it to disconnect if its connected.
       
   783             connection->Disconnect();
       
   784 
       
   785             // Delete the connection object.
       
   786             iBTConnIndex->Remove(connection->ConnID());
       
   787 
       
   788             // Update the stored devices, as we could have power off
       
   789             // and no clean shutdown.
       
   790             // Use the non-leaving version.
       
   791             StoreVirtuallyCabledDevices(KFileStore);
       
   792             }
       
   793 
       
   794         i++;
       
   795         }
       
   796 
       
   797     }
       
   798 
       
   799 /*Asks the server to disconnect all the devices totally,
       
   800  * remove the connection entries from the connection container.
       
   801  */
       
   802 void CBTHidServer::CloseAllBluetoothConnection()
       
   803     {
       
   804     TInt i = 0;
       
   805 
       
   806         TRACE_INFO(_L("[BTHID]\tCBTHidServer::CloseAllBluetoothConnection"));
       
   807 
       
   808     while (i < iBTConnContainer->Count())
       
   809         {
       
   810         CBTHidConnection *connection =
       
   811                 static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
   812         if (connection)
       
   813             {
       
   814             if (connection->IsConnected())
       
   815                 {
       
   816                 // Inform the Generic HID of the disconnection.
       
   817                 iGenHID->Disconnected(connection->ConnID());
       
   818 
       
   819                 // Get it to disconnect if its connected.
       
   820                 connection->Disconnect();
       
   821 
       
   822                 // Delete the connection object.
       
   823                 iBTConnIndex->Remove(connection->ConnID());
       
   824 
       
   825                 // Update the stored devices, as we could have power off
       
   826                 // and no clean shutdown.
       
   827                 // Use the non-leaving version.
       
   828                 StoreVirtuallyCabledDevices(KFileStore);
       
   829                 }
       
   830             }
       
   831 
       
   832         i++;
       
   833         }
       
   834     }
       
   835 
       
   836 void CBTHidServer::DisconnectDeviceL(const TBTDevAddr& aAddress)
       
   837     {
       
   838     TInt i = 0;
       
   839     TBool foundItem = EFalse;
       
   840 
       
   841         TRACE_INFO(_L("[BTHID]\tCBTHidServer::DisconnectDeviceL"));
       
   842     while ((i < iBTConnContainer->Count()) && (!foundItem))
       
   843         {
       
   844         CBTHidConnection *connection =
       
   845                 static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
   846 
       
   847         CBTHidDevice& devDetails = connection->DeviceDetails();
       
   848 
       
   849         if (devDetails.iAddress == aAddress)
       
   850             {
       
   851             foundItem = ETrue;
       
   852 
       
   853             // Drop the bluetooth connection.
       
   854             connection->DropConnection();
       
   855 
       
   856             // Stop the driver.
       
   857             iGenHID->DriverActive(connection->ConnID(),
       
   858                     CHidTransport::ESuspend);
       
   859 
       
   860             InformClientsOfStatusChange(connection->DeviceDetails(),
       
   861                     EBTDeviceDisconnected);
       
   862             //Microsoft Keyboard & other "Unsecure" devices
       
   863             CheckAndSetControlListenerSecurityL(
       
   864                     connection->DeviceDetails().iUseSecurity);
       
   865             }
       
   866 
       
   867         i++;
       
   868         }
       
   869     }
       
   870 
       
   871 void CBTHidServer::DisconnectAllDeviceL()
       
   872     {
       
   873     TInt i = 0;
       
   874 
       
   875         TRACE_INFO(_L("[BTHID]\tCBTHidServer::DisconnectAllDeviceL"));
       
   876     while (i < iBTConnContainer->Count())
       
   877         {
       
   878         CBTHidConnection *connection =
       
   879                 static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
   880 
       
   881         if (connection)
       
   882             {
       
   883             if (connection->IsConnected())
       
   884                 {
       
   885                 CBTHidDevice& devDetails = connection->DeviceDetails();
       
   886 
       
   887                 // Drop the bluetooth connection.
       
   888                 connection->DropConnection();
       
   889 
       
   890                 // Stop the driver.
       
   891                 iGenHID->DriverActive(connection->ConnID(),
       
   892                         CHidTransport::ESuspend);
       
   893 
       
   894                 InformClientsOfStatusChange(devDetails,
       
   895                         EBTDeviceDisconnected);
       
   896                 //Microsoft Keyboard & other "Unsecure" devices
       
   897                 CheckAndSetControlListenerSecurityL(
       
   898                         devDetails.iUseSecurity);
       
   899                 }
       
   900 
       
   901             i++;
       
   902             }
       
   903         }
       
   904     }
       
   905 
       
   906 void CBTHidServer::CheckAndSetControlListenerSecurityL(TBool aSec)
       
   907     {
       
   908 
       
   909         TRACE_INFO( (_L("[BTHID]\tCBTHidServer::CheckAndSetControlListenerSecurityL(%d)"), aSec) );
       
   910 
       
   911     //Checking for Microsoft Keyboard & other "Unsecure" devices
       
   912 
       
   913     if (!aSec) //Security is set on in Constructor of listener. This overrides that setting.
       
   914         {
       
   915         delete iControlListener;
       
   916         iControlListener = NULL;
       
   917         if (iTempControl)
       
   918             iTempControl->Close();
       
   919         iControlListener = CSocketListener::NewL(iSocketServ,
       
   920                 KL2CAPHidControl, *this, EFalse); //iAuthorisationFlag); We need authorisation, unless otherwise stated.
       
   921         User::LeaveIfError(iControlListener->AcceptConnection(*iTempControl));
       
   922         }
       
   923 
       
   924     }
       
   925 
       
   926 // from MBTConnectionObserver
       
   927 void CBTHidServer::HandleControlData(TInt aConnID, const TDesC8& aBuffer)
       
   928     {
       
   929     iGenHID->DataIn(aConnID, CHidTransport::EHidChannelCtrl, aBuffer);
       
   930     }
       
   931 
       
   932 void CBTHidServer::HandleCommandAck(TInt aConnID, TInt aStatus)
       
   933     {
       
   934     iGenHID->CommandResult(aConnID, aStatus);
       
   935     }
       
   936 
       
   937 void CBTHidServer::HandleInterruptData(TInt aConnID, const TDesC8& aBuffer)
       
   938     {
       
   939     iGenHID->DataIn(aConnID, CHidTransport::EHidChannelInt, aBuffer);
       
   940     }
       
   941 
       
   942 void CBTHidServer::FirstTimeConnectionComplete(TInt aConnID, TInt aStatus)
       
   943     {
       
   944         TRACE_INFO( (_L("[BTHID]\tCBTHidServer::FirstTimeConnectionComplete(%d)"), aStatus));
       
   945     TInt error = aStatus;
       
   946 
       
   947     CBTHidConnection* connection =
       
   948             static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
       
   949     __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
       
   950 
       
   951     if (error == KErrNone)
       
   952         {
       
   953         TBool genHidConnected = EFalse;
       
   954 
       
   955             TRAP( error,
       
   956                     // Inform the Generic HID of the Connection
       
   957                     GenericHIDConnectL(connection, ETrue);
       
   958 
       
   959                     // Record that we got as far as informing the Generic HID.
       
   960                     genHidConnected = ETrue;
       
   961 
       
   962                     // Try to start monitoring the channels.
       
   963                     connection->StartMonitoringChannelsL();
       
   964             )
       
   965 
       
   966         if (error != KErrNone)
       
   967             {
       
   968             // If we informed the Generic HID of the connection, then
       
   969             // we must also disconnect.
       
   970             if (genHidConnected)
       
   971                 {
       
   972                 iGenHID->Disconnected(aConnID);
       
   973                 }
       
   974 
       
   975             // Delete the connection object.
       
   976             iBTConnIndex->Remove(aConnID);
       
   977             }
       
   978         else
       
   979             {
       
   980             // Update the stored devices, as we could have power off
       
   981             // and no clean shutdown.
       
   982             // Use the non-leaving version.
       
   983             TRACE_INFO( _L("[BTHID]\tCBTHidServer::FirstTimeConnectionComplete() before CleanOldConnection") );
       
   984             CleanOldConnection(aConnID);
       
   985             TRACE_INFO( _L("[BTHID]\tCBTHidServer::FirstTimeConnectionComplete() after CleanOldConnection") );
       
   986             StoreVirtuallyCabledDevices(KFileStore);
       
   987             }
       
   988         }
       
   989     else
       
   990         {
       
   991         iBTConnIndex->Remove(aConnID);
       
   992         }
       
   993 
       
   994     // Report the connection result to the sessions.
       
   995     iSessionIter.SetToFirst();
       
   996     for (;;)
       
   997         {
       
   998         CBTHidServerSession* session;
       
   999         session = reinterpret_cast<CBTHidServerSession*> (iSessionIter++);
       
  1000         if (!session)
       
  1001             {
       
  1002             break;
       
  1003             }
       
  1004 
       
  1005         session->InformConnectionResult(aConnID, error);
       
  1006         }
       
  1007     }
       
  1008 
       
  1009 void CBTHidServer::LinkLost(TInt aConnID)
       
  1010     {
       
  1011         TRACE_INFO( (_L("[BTHID]\tCBTHidServer::LinkLost(%d)"), aConnID));
       
  1012     // Stop the driver.
       
  1013     iGenHID->DriverActive(aConnID, CHidTransport::ESuspend);
       
  1014 
       
  1015     CBTHidConnection* connection =
       
  1016             static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
       
  1017     __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
       
  1018 
       
  1019     // Inform clients of the change in status of this connection.
       
  1020     InformClientsOfStatusChange(connection->DeviceDetails(),
       
  1021             EBTDeviceLinkLost);
       
  1022     }
       
  1023 
       
  1024 void CBTHidServer::LinkRestored(TInt aConnID)
       
  1025     {
       
  1026     CBTHidConnection* connection =
       
  1027             static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
       
  1028     __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
       
  1029 
       
  1030     // Inform the Generic HID of the reconnection
       
  1031     TInt error = iGenHID->DriverActive(aConnID, CHidTransport::EActive);
       
  1032 
       
  1033     // If there was no error, try to start monitoring the channels.
       
  1034     if (error == KErrNone)
       
  1035         {
       
  1036             // Try to start monitoring channels.
       
  1037             TRAP( error, connection->StartMonitoringChannelsL(); )
       
  1038         }
       
  1039 
       
  1040     // Report new connection status.
       
  1041     if (error == KErrNone)
       
  1042         {
       
  1043         InformClientsOfStatusChange(connection->DeviceDetails(),
       
  1044                 EBTDeviceLinkRestored);
       
  1045         }
       
  1046     else
       
  1047         {
       
  1048         InformClientsOfStatusChange(connection->DeviceDetails(),
       
  1049                 EBTDeviceUnplugged);
       
  1050         // Inform the Generic HID of the disconnection.
       
  1051         iGenHID->Disconnected(aConnID);
       
  1052         // Delete the connection object.
       
  1053         iBTConnIndex->Remove(aConnID);
       
  1054 
       
  1055         // Update the stored devices, as we could have power off
       
  1056         // and no clean shutdown.
       
  1057         // Use the non-leaving version.
       
  1058         StoreVirtuallyCabledDevices(KFileStore);
       
  1059         }
       
  1060     }
       
  1061 
       
  1062 void CBTHidServer::Disconnected(TInt aConnID)
       
  1063     {
       
  1064     CBTHidConnection *connection =
       
  1065             static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
       
  1066     __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
       
  1067 
       
  1068     // Stop the driver.
       
  1069     iGenHID->DriverActive(aConnID, CHidTransport::ESuspend);
       
  1070 
       
  1071     // Report new connection status.
       
  1072     InformClientsOfStatusChange(connection->DeviceDetails(),
       
  1073             EBTDeviceDisconnected);
       
  1074 
       
  1075         //Check if no security is needed for listening socket
       
  1076         //Microsoft Keyboard & other "Unsecure" devices need this.
       
  1077 
       
  1078         // possible leave is sign of severe problems in BT stack. So no reason to handle leave.
       
  1079         TRAP_IGNORE( CheckAndSetControlListenerSecurityL(connection->DeviceDetails().iUseSecurity) );
       
  1080 
       
  1081     }
       
  1082 
       
  1083 void CBTHidServer::Unplugged(TInt aConnID)
       
  1084     {
       
  1085     CBTHidConnection *connection =
       
  1086             static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
       
  1087     __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
       
  1088 
       
  1089     // Report new connection status.
       
  1090     InformClientsOfStatusChange(connection->DeviceDetails(),
       
  1091             EBTDeviceUnplugged);
       
  1092 
       
  1093     // Inform the Generic HID of the disconnection.
       
  1094     iGenHID->Disconnected(aConnID);
       
  1095 
       
  1096     iBTConnIndex->Remove(aConnID);
       
  1097 
       
  1098     // Update the stored devices, as we could have power off
       
  1099     // and no clean shutdown.
       
  1100     // Use the non-leaving version.
       
  1101     StoreVirtuallyCabledDevices(KFileStore);
       
  1102     }
       
  1103 
       
  1104 //from MListenerObserver
       
  1105 void CBTHidServer::SocketAccepted(TUint aPort, TInt aErrorCode)
       
  1106     {
       
  1107     TBTSockAddr sockAddr;
       
  1108     TBTDevAddr devAddr;
       
  1109 
       
  1110         TRACE_INFO( (_L("[BTHID]\tCBTHidServer::SocketAccepted, port=%d, error code=%d"), aPort, aErrorCode) );
       
  1111 
       
  1112     // Check error code
       
  1113     if (aErrorCode != KErrNone)
       
  1114         {
       
  1115         // If we do get an error there isn't much we can about it.
       
  1116         // Just tidy up.
       
  1117 
       
  1118         ShutdownListeners(aErrorCode);
       
  1119         }
       
  1120     else
       
  1121         {
       
  1122         TInt i = 0;
       
  1123         TInt count = iBTConnContainer->Count();
       
  1124         TInt err = KErrNone;
       
  1125 
       
  1126         // Check which port has accepted a connection
       
  1127         switch (aPort)
       
  1128             {
       
  1129             // The HID Control Channel
       
  1130             case KL2CAPHidControl:
       
  1131                 // Get the BT address of the device that has connected
       
  1132                 iTempControl->RemoteName(sockAddr);
       
  1133                 devAddr = sockAddr.BTAddr();
       
  1134                 if (IsAllowToConnectFromClientSide(devAddr))
       
  1135                     {
       
  1136                     while ((i < count) && (iTempControl))
       
  1137                         {
       
  1138                         CBTHidConnection
       
  1139                                 * connection =
       
  1140                                         static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
  1141                         __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
       
  1142                         connection->OfferControlSocket(devAddr, iTempControl);
       
  1143                         i++;
       
  1144                         }
       
  1145 
       
  1146                     }
       
  1147                 else
       
  1148                     {
       
  1149                     InformStatusChange(devAddr, EBTDeviceAnotherExist);
       
  1150                     }
       
  1151 
       
  1152                 // The next socket to accept into
       
  1153                 if (iTempControl)
       
  1154                     {
       
  1155                     // Reuse this socket
       
  1156                     iTempControl->Close();
       
  1157                     err = KErrNone;
       
  1158                     }
       
  1159                 else
       
  1160                     {
       
  1161                     // Socket ownership has been transferred so create a new
       
  1162                     // socket
       
  1163                     //TRAP( err, iTempControl = new (ELeave) RSocket; )
       
  1164                     iTempControl = new RSocket;
       
  1165                     }
       
  1166 
       
  1167                 // Created a socket to accept into so accept next connection
       
  1168                 if (err == KErrNone)
       
  1169                     {
       
  1170                     err = iControlListener->AcceptConnection(*iTempControl);
       
  1171                     }
       
  1172 
       
  1173                 // If we failed to allocate a new RSocket or failed
       
  1174                 // in the AcceptConnectionL call it means we can no longer
       
  1175                 // accept connections from a device.
       
  1176                 if (err != KErrNone)
       
  1177                     {
       
  1178                         TRACE_INFO(_L("[BTHID]\tCBTHidServer::SocketAccepted, control channel failed, shutdown listener"));
       
  1179                     ShutdownListeners(err);
       
  1180                     }
       
  1181 
       
  1182                 break;
       
  1183 
       
  1184                 // The HID Interrupt Channel
       
  1185             case KL2CAPHidInterrupt:
       
  1186                 // Get the BT address of the device that has connected
       
  1187                 iTempInterrupt->RemoteName(sockAddr);
       
  1188                 devAddr = sockAddr.BTAddr();
       
  1189                 if (IsAllowToConnectFromClientSide(devAddr))
       
  1190                     {
       
  1191                     while ((i < count) && (iTempInterrupt))
       
  1192                         {
       
  1193                         CBTHidConnection
       
  1194                                 *connection =
       
  1195                                         static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
  1196                         __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
       
  1197                         connection->OfferInterruptSocket(devAddr,
       
  1198                                 iTempInterrupt);
       
  1199                         i++;
       
  1200                         }
       
  1201                     }
       
  1202                 else
       
  1203                     {
       
  1204                     //Commented for avoiding display the same notes twice for same device
       
  1205                     //because of two channels(Control+Interrupt) has been rejected
       
  1206                     //InformStatusChange(devAddr, EBTDeviceAnotherExist);
       
  1207                     }
       
  1208 
       
  1209                 // The next socket to accept into
       
  1210                 if (iTempInterrupt)
       
  1211                     {
       
  1212                     // Reuse this socket
       
  1213                     iTempInterrupt->Close();
       
  1214                     err = KErrNone;
       
  1215                     }
       
  1216                 else
       
  1217                     {
       
  1218                     // Socket ownership has been transferred so create a new
       
  1219                     // socket
       
  1220                     //TRAP( err, iTempInterrupt = new (ELeave) RSocket; )
       
  1221                     iTempInterrupt = new RSocket;
       
  1222                     }
       
  1223 
       
  1224                 // Created a socket to accept into so accept next connection
       
  1225                 if (err == KErrNone)
       
  1226                     {
       
  1227                     err = iInterruptListener->AcceptConnection(
       
  1228                             *iTempInterrupt);
       
  1229                     }
       
  1230 
       
  1231                 // If we failed to allocate a new RSocket or failed
       
  1232                 // in the AcceptConnectionL call it means we can no longer
       
  1233                 // accept connections from a device.
       
  1234                 if (err != KErrNone)
       
  1235                     {
       
  1236                         TRACE_INFO(_L("[BTHID]\tCBTHidServer::SocketAccepted, interrupt channel failed, shutdown listener"));
       
  1237                     ShutdownListeners(err);
       
  1238                     }
       
  1239                 break;
       
  1240 
       
  1241             default:
       
  1242                 PanicServer(EInvalidHandle);
       
  1243                 break;
       
  1244             }
       
  1245         }
       
  1246 
       
  1247     }
       
  1248 
       
  1249 //from MTransportLayer
       
  1250 TUint CBTHidServer::CountryCodeL(TInt aConnID)
       
  1251     {
       
  1252     // Identify the connection object.
       
  1253     CBTHidConnection* conn = IdentifyConnectionL(aConnID);
       
  1254     // Retrieve its device details.
       
  1255     const CBTHidDevice& device = conn->DeviceDetails();
       
  1256 
       
  1257     //return the country code
       
  1258     return device.iCountryCode;
       
  1259     }
       
  1260 
       
  1261 TUint CBTHidServer::VendorIdL(TInt aConnID)
       
  1262     {
       
  1263     // Identify the connection object.
       
  1264     CBTHidConnection* conn = IdentifyConnectionL(aConnID);
       
  1265     // Retrieve its device details.
       
  1266     const CBTHidDevice& device = conn->DeviceDetails();
       
  1267 
       
  1268     //return the Vendor Id.
       
  1269     return device.iVendorID;
       
  1270     }
       
  1271 
       
  1272 TUint CBTHidServer::ProductIdL(TInt aConnID)
       
  1273     {
       
  1274     // Identify the connection object.
       
  1275     CBTHidConnection* conn = IdentifyConnectionL(aConnID);
       
  1276     // Retrieve its device details.
       
  1277     const CBTHidDevice& device = conn->DeviceDetails();
       
  1278 
       
  1279     //return the Product Id.
       
  1280     return device.iProductID;
       
  1281     }
       
  1282 
       
  1283 void CBTHidServer::GetProtocolL(TInt aConnID, TUint16 /*aInterface*/)
       
  1284     {
       
  1285     CBTHidConnection *connection = IdentifyConnectionL(aConnID);
       
  1286 
       
  1287     // Bluetooth HID only has one interface. We don't need the interface param.
       
  1288     connection->GetProtocolL();
       
  1289     }
       
  1290 
       
  1291 void CBTHidServer::SetProtocolL(TInt aConnID, TUint16 aValue, TUint16 /*aInterface*/)
       
  1292     {
       
  1293     CBTHidConnection *connection = IdentifyConnectionL(aConnID);
       
  1294 
       
  1295     // Bluetooth HID only has one interface. We don't need the interface param.
       
  1296     connection->SetProtocolL(aValue);
       
  1297     }
       
  1298 
       
  1299 void CBTHidServer::GetReportL(TInt aConnID, TUint8 aReportType,
       
  1300         TUint8 aReportID, TUint16 /*aInterface*/, TUint16 aLength)
       
  1301     {
       
  1302     CBTHidConnection *connection = IdentifyConnectionL(aConnID);
       
  1303 
       
  1304     // Bluetooth HID only has one interface. We don't need the interface param.
       
  1305     connection->GetReportL(aReportType, aReportID, aLength);
       
  1306     }
       
  1307 
       
  1308 void CBTHidServer::SetReportL(TInt aConnID, TUint8 aReportType,
       
  1309         TUint8 aReportID, TUint16 /*aInterface*/, const TDesC8& aReport)
       
  1310     {
       
  1311     CBTHidConnection *connection = IdentifyConnectionL(aConnID);
       
  1312 
       
  1313     // Bluetooth HID only has one interface. We don't need the interface param
       
  1314     connection->SetReportL(aReportType, aReportID, aReport);
       
  1315     }
       
  1316 
       
  1317 void CBTHidServer::DataOutL(TInt aConnID, TUint8 aReportID,
       
  1318         TUint16 /*aInterface*/, const TDesC8& aReport)
       
  1319     {
       
  1320     CBTHidConnection *connection = IdentifyConnectionL(aConnID);
       
  1321 
       
  1322     // Bluetooth HID only has one interface. We don't need the interface param
       
  1323     connection->DataOutL(aReportID, aReport); //we disregard DATA Input, DATA Feature and DATA Other
       
  1324     }
       
  1325 
       
  1326 void CBTHidServer::GetIdleL(TInt aConnID, TUint8 /*aReportID*/, TUint16 /*aInterface*/)
       
  1327     {
       
  1328     CBTHidConnection *connection = IdentifyConnectionL(aConnID);
       
  1329 
       
  1330     // Bluetooth HID only has one interface. We don't need the interface param.
       
  1331     // Bluetooth HID doesn't specify Report ID.
       
  1332     connection->GetIdleL();
       
  1333     }
       
  1334 
       
  1335 void CBTHidServer::SetIdleL(TInt aConnID, TUint8 aDuration,
       
  1336         TUint8 /*aReportID*/, TUint16 /*aInterface*/)
       
  1337     {
       
  1338     CBTHidConnection *connection = IdentifyConnectionL(aConnID);
       
  1339 
       
  1340     // Bluetooth HID only has one interface. We don't need the interface param.
       
  1341     // Bluetooth HID doesn't specify Report ID.
       
  1342     connection->SetIdleL(aDuration);
       
  1343     }
       
  1344 
       
  1345 CBTHidConnection* CBTHidServer::IdentifyConnectionL(TInt aConnID) const
       
  1346     {
       
  1347     CBTHidConnection *connection =
       
  1348             static_cast<CBTHidConnection*> (iBTConnIndex->At(aConnID));
       
  1349 
       
  1350     if (!connection)
       
  1351         {
       
  1352         User::Leave(KErrNotFound);
       
  1353         }
       
  1354 
       
  1355     return connection;
       
  1356     }
       
  1357 
       
  1358 void CBTHidServer::LoadVirtuallyCabledDevicesL(const TDesC& aStoreName)
       
  1359     {
       
  1360         TRACE_INFO(_L("[BTHID]\tCBTHidServer::LoadVirtuallyCabledDevicesL"));
       
  1361     // Create the parsed name and open the store
       
  1362     TParse parsedName;
       
  1363     User::LeaveIfError(iFs.Parse(aStoreName, parsedName));
       
  1364 
       
  1365     CFileStore* store = CDirectFileStore::OpenLC(iFs, parsedName.FullName(),
       
  1366             EFileRead);
       
  1367 
       
  1368     // Open the data stream inside the store
       
  1369     RStoreReadStream stream;
       
  1370     stream.OpenLC(*store, store->Root());
       
  1371 
       
  1372     // Read the version number of the data file.
       
  1373     // Its not used in this version.
       
  1374     stream.ReadInt32L();
       
  1375 
       
  1376     // Get the number of devices to load.
       
  1377     TInt count = stream.ReadInt32L();
       
  1378     TInt i;
       
  1379     for (i = 0; i < count; i++)
       
  1380         {
       
  1381         // Create the connection object. Ok to leave.
       
  1382         CBTHidConnection* connection = CBTHidConnection::NewLC(iSocketServ,
       
  1383                 *this, ENotConnected);
       
  1384 
       
  1385         stream >> connection->DeviceDetails();
       
  1386         // Check if no security is needed, then override earlier Control listener with unsecure one.
       
  1387         // This is needed for Microsoft Keyboard fix.
       
  1388         CheckAndSetControlListenerSecurityL(
       
  1389                 connection->DeviceDetails().iUseSecurity);
       
  1390 
       
  1391         // Add to the connection container object.
       
  1392         iBTConnContainer->AddL(connection);
       
  1393         CleanupStack::Pop(); // connection
       
  1394 
       
  1395         // We can't let this just leave since we have already inserted the
       
  1396         // connection object into the container.
       
  1397         TBool connectionIndexed = EFalse;
       
  1398         TRAPD( res,
       
  1399                 // Now add the object to the index to get an id.
       
  1400                 TInt id = iBTConnIndex->AddL(connection);
       
  1401                 connection->SetConnID(id);
       
  1402                 connectionIndexed = ETrue;
       
  1403                 connection->ReconnectL();
       
  1404 
       
  1405                 // Inform the Generic HID of the connection, but don't
       
  1406                 // start the driver yet. This will be done in LinkRestored.
       
  1407                 GenericHIDConnectL(connection, EFalse);
       
  1408         )
       
  1409 
       
  1410         if (res != KErrNone)
       
  1411             {
       
  1412             if (connectionIndexed)
       
  1413                 {
       
  1414                 // Connection object was added to the index, but reconnection
       
  1415                 // failed.
       
  1416                 iBTConnIndex->Remove(connection->ConnID());
       
  1417                 }
       
  1418             else
       
  1419                 {
       
  1420                 // Couldn't make an index entry.
       
  1421                 // Close the connection object, causing it to be removed from
       
  1422                 // the container.
       
  1423                 connection->Close();
       
  1424                 }
       
  1425             }
       
  1426         }
       
  1427 
       
  1428     // Delete all the remaining stuff on the cleanup stack
       
  1429     // (store and stream)
       
  1430     CleanupStack::PopAndDestroy(2);
       
  1431     }
       
  1432 
       
  1433 void CBTHidServer::StoreVirtuallyCabledDevicesL(const TDesC& aStoreName)
       
  1434     {
       
  1435         TRACE_INFO(_L("[BTHID]\tCBTHidServer::StoreVirtuallyCabledDevicesL"));
       
  1436     // Parse the filestore name into a usable version.
       
  1437     TParse parsedName;
       
  1438     User::LeaveIfError(iFs.Parse(aStoreName, parsedName));
       
  1439 
       
  1440     // Count the number of devices that we will need to store.
       
  1441     // Also count the accumulated disk size require for each one.
       
  1442     TInt numVirtuallyCabled = 0;
       
  1443     TInt requiredDiskSize = 0;
       
  1444 
       
  1445     TInt i;
       
  1446 
       
  1447     for (i = 0; i < iBTConnContainer->Count(); i++)
       
  1448         {
       
  1449         CBTHidConnection *connection =
       
  1450                 static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
  1451 
       
  1452         if (connection)
       
  1453             {
       
  1454             CBTHidDevice &device = connection->DeviceDetails();
       
  1455             if (device.iVirtuallyCabled)
       
  1456                 {
       
  1457                 numVirtuallyCabled++;
       
  1458                 // Increase the required size.
       
  1459                 requiredDiskSize += device.DiskSize();
       
  1460                 }
       
  1461             }
       
  1462         }
       
  1463 
       
  1464     // Check for required disk size
       
  1465     // NOTE !! Be careful when changing functionality in here
       
  1466 
       
  1467     // We have the number of bytes required to store all the device objects
       
  1468     // we want to store
       
  1469 
       
  1470     // First thing written will be the file version which is 4 bytes
       
  1471     // Then the number of virtually cabled devices which is 4 bytes
       
  1472     requiredDiskSize += 8;
       
  1473 
       
  1474         TRACE_INFO( (_L("[BTHID]\tCBTHidServer::StoreVirtuallyCabledDevicesL: Required disk size %d bytes"),
       
  1475                         requiredDiskSize) );
       
  1476     // Now check that the required number of bytes will not take us into
       
  1477     // the critical disk space area.
       
  1478     if (SysUtil::DiskSpaceBelowCriticalLevelL(&iFs, requiredDiskSize, EDriveC))
       
  1479         {
       
  1480         User::Leave(KErrDiskFull);
       
  1481         }
       
  1482 
       
  1483     // Start the write for real.
       
  1484 
       
  1485     CFileStore* store = CDirectFileStore::ReplaceLC(iFs,
       
  1486             parsedName.FullName(), EFileWrite);
       
  1487     store->SetTypeL(KDirectFileStoreLayoutUid);
       
  1488 
       
  1489     // Create the stream
       
  1490     RStoreWriteStream stream;
       
  1491     TStreamId id = stream.CreateLC(*store);
       
  1492 
       
  1493     // Write the version number of the data file
       
  1494     stream.WriteInt32L(KDataFileVersionNumber);
       
  1495 
       
  1496     // Write the number of devices we are going to store.
       
  1497     stream.WriteInt32L(numVirtuallyCabled);
       
  1498 
       
  1499     // Externalise each device object that is virtually cabled.
       
  1500     for (i = 0; i < iBTConnContainer->Count(); i++)
       
  1501         {
       
  1502         CBTHidConnection *connection =
       
  1503                 static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
       
  1504 
       
  1505         if (connection)
       
  1506             {
       
  1507             CBTHidDevice &device = connection->DeviceDetails();
       
  1508             if (device.iVirtuallyCabled)
       
  1509                 {
       
  1510                 stream << device;
       
  1511                 }
       
  1512             }
       
  1513 
       
  1514         }
       
  1515 
       
  1516     // Commit the changes to the stream
       
  1517     stream.CommitL();
       
  1518     CleanupStack::PopAndDestroy();
       
  1519 
       
  1520     // Set the stream in the store and commit the store
       
  1521     store->SetRootL(id);
       
  1522     store->CommitL();
       
  1523     CleanupStack::PopAndDestroy();
       
  1524     }
       
  1525 
       
  1526 void CBTHidServer::StoreVirtuallyCabledDevices(const TDesC& aStoreName)
       
  1527     {
       
  1528         TRAP_IGNORE( StoreVirtuallyCabledDevicesL(aStoreName);)
       
  1529     }
       
  1530 
       
  1531 void RunServerL()
       
  1532     {
       
  1533         TRACE_FUNC_ENTRY
       
  1534     User::RenameThread(KBTHidSrvName);
       
  1535     // Create and install the active scheduler for this thread.
       
  1536     CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
       
  1537     CleanupStack::PushL(scheduler);
       
  1538     CActiveScheduler::Install(scheduler);
       
  1539     // create the server (leave it on the cleanup stack)
       
  1540     CBTHidServer* btHidServer = CBTHidServer::NewLC();
       
  1541     // Initialisation complete, now signal the client
       
  1542     RProcess::Rendezvous(KErrNone);
       
  1543         // The server is not up and running.
       
  1544         TRACE_INFO( ( _L( "[BTHID]\t BTHID server now up and running" ) ) )
       
  1545     // The active scheduler runs during the lifetime of this thread.
       
  1546     CActiveScheduler::Start();
       
  1547     // Cleanup the server and scheduler.
       
  1548     CleanupStack::PopAndDestroy(btHidServer);
       
  1549     CleanupStack::PopAndDestroy(scheduler);
       
  1550         TRACE_FUNC_EXIT
       
  1551     }
       
  1552 
       
  1553 GLDEF_C TInt E32Main()
       
  1554     {
       
  1555     __UHEAP_MARK;
       
  1556         TRACE_FUNC_ENTRY
       
  1557     CTrapCleanup* cleanup = CTrapCleanup::New();
       
  1558     TInt err = KErrNoMemory;
       
  1559     if (cleanup)
       
  1560         {
       
  1561             TRAP( err, RunServerL() );
       
  1562         delete cleanup;
       
  1563         }
       
  1564     __UHEAP_MARKEND;
       
  1565     return err;
       
  1566     }
       
  1567 
       
  1568 // CBTHidNotifierHelper
       
  1569 
       
  1570 CBTHidNotifierHelper* CBTHidNotifierHelper::NewL(CBTHidServer& aHidServer, TInt aNote, const TBTDevAddr& aDeviceAddr)
       
  1571     { 
       
  1572     CBTHidNotifierHelper* self = new(ELeave) CBTHidNotifierHelper(aHidServer, aNote, aDeviceAddr);
       
  1573     CleanupStack::PushL(self);
       
  1574     self->ConstructL();
       
  1575     CleanupStack::Pop(self);
       
  1576     return self;
       
  1577     }
       
  1578 
       
  1579 CBTHidNotifierHelper::~CBTHidNotifierHelper()
       
  1580     {
       
  1581     Cancel();
       
  1582     iNotifier.Close();
       
  1583     }   
       
  1584 
       
  1585 void CBTHidNotifierHelper::Start()
       
  1586     {   
       
  1587     TRACE_INFO(_L("CBTHidNotifierHelper::Start()..."));
       
  1588     
       
  1589     // Simple async handling
       
  1590     iNotifier.StartNotifierAndGetResponse(iStatus,
       
  1591                     KBTGenericInfoNotifierUid, iGenericInfoNotifierType,
       
  1592                     iNoResult);
       
  1593     
       
  1594     // assert object is not already active
       
  1595     __ASSERT_DEBUG(!IsActive(), CBTHidServer::PanicServer(ENotifierAlreadyActive));
       
  1596     
       
  1597     SetActive();
       
  1598     }           
       
  1599 
       
  1600 void CBTHidNotifierHelper::DoCancel()
       
  1601     {
       
  1602     TRACE_INFO(_L("CBTHidNotifierHelper::DoCancel()..."));
       
  1603     
       
  1604     iNotifier.CancelNotifier(KBTGenericInfoNotifierUid);
       
  1605     }
       
  1606 
       
  1607 CBTHidNotifierHelper::CBTHidNotifierHelper(CBTHidServer& aHidServer, TInt aNote, const TBTDevAddr& aDeviceAddr)
       
  1608     : CActive(CActive::EPriorityStandard),
       
  1609     iHidServer(aHidServer)
       
  1610     {
       
  1611     TRACE_INFO(_L("CBTHidNotifierHelper::CBTHidNotifierHelper()..."));
       
  1612     
       
  1613     iGenericInfoNotifierType().iMessageType = (TBTGenericInfoNoteType) aNote;
       
  1614     iGenericInfoNotifierType().iRemoteAddr.Copy(aDeviceAddr.Des());
       
  1615     
       
  1616     CActiveScheduler::Add(this);
       
  1617     }
       
  1618     
       
  1619 void CBTHidNotifierHelper::ConstructL()
       
  1620     {
       
  1621     TRACE_INFO(_L("CBTHidNotifierHelper::ConstructL()..."));
       
  1622     
       
  1623     User::LeaveIfError(iNotifier.Connect());
       
  1624     }
       
  1625     
       
  1626 void CBTHidNotifierHelper::RunL()
       
  1627     {
       
  1628     TRACE_INFO(_L("CBTHidNotifierHelper::RunL()..."));
       
  1629     
       
  1630     iHidServer.NotifierRequestCompleted();
       
  1631     }