/bluetoothengine/bthid/bthidserver/src/bthidserver.cpp
C++ | 1825 lines | 1263 code | 309 blank | 253 comment | 183 complexity | 37be49aa0b95e0d401204f8aeb60066f MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * 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"
- #include "hidsdpclient.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;
-
- delete iHidSdpClient;
-
- }
- 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"));
-
-
- 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 ||
- aState == EBTDeviceConnectedFromRemote)
- {
- 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:
- case EBTDeviceConnectedFromRemote:
- {
- 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) ||
- (EHIDInitConnecting == HidConnectionStatus) )
- {
- retVal = EBTEngConnecting;
- }
- if (EConnected == HidConnectionStatus)
- {
- retVal = EBTEngConnected;
- }
- }
- }
- i++;
- }
- return retVal;
- }
- TBool CBTHidServer::DeviceExistInContainer(const TBTDevAddr& aAddress)
- {
- TInt i = 0;
- TBool foundItem = EFalse;
- TInt BTConnectionObjCount = iBTConnContainer->Count();
- TRACE_INFO(_L("[BTHID]\tCBTHidServer::DeviceExistInContainer()"));
- while ((i < BTConnectionObjCount) && (!foundItem))
- {
- CBTHidConnection *connection =
- static_cast<CBTHidConnection*> ((*iBTConnContainer)[i]);
- if (connection)
- {
- CBTHidDevice& devDetails = connection->DeviceDetails();
- if (devDetails.iAddress == aAddress)
- {
- foundItem = ETrue;
- }
- }
- i++;
- }
- return foundItem;
- }
- 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 ||
- HidConnectionStatus == EHIDInitConnecting)
- {
- 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() BTConnectionObjCount = %d"), BTConnectionObjCount) );
- 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 ||
- HidConnectionStatus == EHIDInitConnecting)
- {
- if (devDetails.iAddress != aDevAddr)
- {
- if ((IsKeyboard(deviceSubClass) && IsKeyboard(
- devDetails.iDeviceSubClass)) || (IsPointer(
- deviceSubClass) && IsPointer(
- devDetails.iDeviceSubClass)))
- {
- TRACE_INFO(_L("[BTHID]\tCBTHidServer::() NO connection allowed, connection exist already!"));
- 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(TBTConnectionState aConnectionStatus)
- {
- TRACE_INFO(_L("[BTHID]\tCBTHidServer::NewConnectionL"));
- __ASSERT_DEBUG( aConnectionStatus == EConnecting || aConnectionStatus == EHIDInitConnecting ,
- CBTHidServer::PanicServer(EBadState));
-
- CBTHidConnection *connection = CBTHidConnection::NewLC(iSocketServ,
- *this, aConnectionStatus);
- // 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();
-
- InformClientsOfStatusChange(connection->DeviceDetails(),
- EBTDeviceDisconnected);
-
- // 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();
-
- InformClientsOfStatusChange(connection->DeviceDetails(),
- EBTDeviceDisconnected);
-
- // 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::FirstTimeConnectionCompleteFromRemote(TInt aConnID, TInt aStatus)
- {
- TRACE_INFO( (_L("[BTHID]\tCBTHidServer::FirstTimeConnectionCompleteFromRemote(%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.
- //Quietly refuse the remote initialized connection in case of error.
- //No need to bother user.
- iBTConnIndex->Remove(aConnID);
- }
- else
- {
- // Update the stored devices, as we could have power off
- // and no clean shutdown.
- // Use the non-leaving version.
- CleanOldConnection(aConnID);
- StoreVirtuallyCabledDevices(KFileStore);
- InformClientsOfStatusChange(connection->DeviceDetails(),
- EBTDeviceConnectedFromRemote);
- }
- }
- else
- {
- //Quietly refuse the remote initialized connection in case of error.
- //No need to bother user.
- iBTConnIndex->Remove(aConnID);
- }
- }
- void CBTHidServer::StartSDPSearch(TInt aConnID)
- {
- iConnID = aConnID;
- TRACE_INFO( (_L("[BTHID]\tCBTHidServer::StartSDPSearch aConnID= (%d)"), aConnID));
- CBTHidConnection* connection =
- static_cast<CBTHidConnection*> (iBTConnIndex->At(iConnID));
- __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
-
- TRAPD( res,
- // Retrieve the hid device object for this new connection
- CBTHidDevice &devDetails =
- ConnectionDetailsL(iConnID);
- // Create a new HID Sdp Client
- // Its only used here so it doesn't matter if we leave.
- delete iHidSdpClient;
- iHidSdpClient = 0;
- //Create a new hid sdp client using the hid device object.
- iHidSdpClient = CHidSdpClient::NewL(devDetails, *this);
- // Start the hid sdp client
- iHidSdpClient->StartL();
- )
-
- if (res != KErrNone)
- {
- // Get the server to delete the new connection object
- DeleteNewConnection(iConnID);
- }
- }
- void CBTHidServer::HidSdpSearchComplete(TInt aResult)
- {
- TRACE_FUNC(_L("[BTHID]\tCBTHidServer::HidSdpSearchComplete"));
- // This is a callback from the Hid SDP client so we can't delete it here
- // Get it to destroy itself when its convenient.
- iHidSdpClient->Kill();
- // Deleted outside destructor.
- iHidSdpClient = 0;
- // If the SDP search was a success
- if (aResult == KErrNone)
- {
- // Try to connect to the device as a HID
- CBTHidConnection* connection =
- static_cast<CBTHidConnection*> (iBTConnIndex->At(iConnID));
- __ASSERT_ALWAYS(connection, PanicServer(EInvalidHandle));
- if (connection)
- {
- CBTHidDevice& devDetails = connection->DeviceDetails();
-
- //Only after SDP search complete, do we know the CoD which is needed
- //to tell if the incoming connection is allowed or not.
- //ETrue , establish the connection.
- //EFalse, refuse the remote connecion sliently
- if (IsAllowToConnectFromClientSide(devDetails.iAddress))
- {
- FirstTimeConnectionCompleteFromRemote(iConnID, aResult);
- }
- else
- {
- FirstTimeConnectionCompleteFromRemote(iConnID, KErrAlreadyExists);
- }
- }
-
- }
- }
- 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 err = KErrNone;
- TInt connectingID = 0;
- // 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();
- // incoming HID connection is allowed
- if (!DeviceExistInContainer(devAddr))
- {
- TRAPD( res,
- // to be created as New if device not yet listed in container
- connectingID = NewConnectionL(EHIDInitConnecting);
-
- // Retrieve the hid device object for this new connection
- CBTHidDevice &devDetails =
- ConnectionDetailsL(connectingID);
- // Fill in the information we got from the client
- devDetails.iAddress = devAddr;
- devDetails.iUseSecurity = ETrue;
- )
- if (res != KErrNone && connectingID != 0)
- {
- // Get the server to delete the new connection object
- DeleteNewConnection(connectingID);
- }
- }
- if (IsAllowToConnectFromClientSide(devAddr))
- {
- TInt count = iBTConnContainer->Count();
- 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))
- {
- TInt count = iBTConnContainer->Count();
- 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& aStoreN…
Large files files are truncated, but you can click here to view the full file