--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/headsetsimulator/core/src/RemoteControl/hsremotecontrolserver.cpp Wed Sep 15 15:59:44 2010 +0200
@@ -0,0 +1,534 @@
+/*
+ * Component Name: Headset Simulator
+ * Author: Comarch S.A.
+ * Version: 1.0
+ * Copyright (c) 2010 Comarch S.A.
+ *
+ * This Software is submitted by Comarch S.A. to Symbian Foundation Limited on
+ * the basis of the Member Contribution Agreement entered between Comarch S.A.
+ * and Symbian Foundation Limited on 5th June 2009 (“Agreement”) and may be
+ * used only in accordance with the terms and conditions of the Agreement.
+ * Any other usage, duplication or redistribution of this Software is not
+ * allowed without written permission of Comarch S.A.
+ *
+ */
+#include "hsremotecontrolserver.h"
+#include "hscore.h"
+#include "hsremotecontroldatahandler.h"
+#include "hsremotecontroltools.h"
+#include "debug.h"
+
+_LIT8(KHsATVGS,"AT+VGS=");
+_LIT8(KHsATCommandEnding,"\r\n");
+_LIT8(KHsATVGM,"AT+VGM=");
+
+CHsControlServer* CHsControlServer::NewL( RSocketServ& aSocketServ,
+ CHsCore* aHsCore )
+ {
+ CHsControlServer* self = CHsControlServer::NewLC( aSocketServ, aHsCore );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+CHsControlServer* CHsControlServer::NewLC( RSocketServ& aSocketServ,
+ CHsCore* aHsCore )
+ {
+ CHsControlServer* self = new ( ELeave ) CHsControlServer( aSocketServ,
+ aHsCore );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+CHsControlServer::CHsControlServer( RSocketServ& aSocketServ, CHsCore* aHsCore ) :
+ iState( ENone ), iSocketServ( aSocketServ ), iHsCore( aHsCore )
+ {
+ }
+
+void CHsControlServer::ConstructL()
+ {
+ iDataHandler = CHsRemoteControlDataHandler::NewL();
+ }
+
+CHsControlServer::~CHsControlServer()
+ {
+ TRACE_FUNC_ENTRY
+ CancelListen();
+ if ( iSocket )
+ {
+ delete iSocket;
+ }
+ if ( iListenSocket )
+ {
+ delete iListenSocket;
+ }
+ if ( iDataHandler )
+ {
+ delete iDataHandler;
+ }
+
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::StartRemoteControlServerL()
+ {
+ TRACE_FUNC_ENTRY
+
+ if ( iState != ENone )
+ {
+ TRACE_INFO (_L("ControlServer is already listening"))
+ TRACE_FUNC_EXIT
+ User::Leave( KErrInUse );
+ }
+
+ iState = EConnecting;
+ TProtocolDesc ProtocolDesc;
+ User::LeaveIfError( iSocketServ.FindProtocol( KHsRFComm(), ProtocolDesc ) );
+
+ if ( iListenSocket )
+ {
+ // Return value may be ignored
+ iListenSocket->Shutdown( RSocket::EImmediate );
+ delete iListenSocket;
+ iListenSocket = NULL;
+ }
+ iListenSocket = CBluetoothSocket::NewL( *this, iSocketServ,
+ ProtocolDesc.iSockType, ProtocolDesc.iProtocol );
+
+ User::LeaveIfError( iListenSocket->GetOpt(
+ KRFCOMMGetAvailableServerChannel, KSolBtRFCOMM, iServerPort ) );
+
+ TBTSockAddr btSockAddr;
+ btSockAddr.SetPort( iServerPort );
+
+ RegisterSdpL( iServerPort );
+ User::LeaveIfError( iListenSocket->Bind( btSockAddr ) );
+
+ TRACE_INFO( ( _L("Control Server port = %d"), iServerPort) )
+ User::LeaveIfError( iListenSocket->Listen( KHsSizeOfListenQueue ) );
+
+ TBTServiceSecurity secSettings;
+ TUid settingsUID = TUid::Uid( (TInt) KHsRemoteControlServiceID );
+ secSettings.SetUid( settingsUID );
+ secSettings.SetAuthentication( EFalse );
+ secSettings.SetAuthorisation( EFalse );
+ secSettings.SetEncryption( EFalse );
+
+ btSockAddr.SetSecurity( secSettings );
+
+ if ( iSocket )
+ {
+ // Return value may be ignored
+ iSocket->Shutdown( RSocket::EImmediate );
+ delete iSocket;
+ iSocket = NULL;
+ }
+ iSocket = CBluetoothSocket::NewL( *this, iSocketServ );
+ User::LeaveIfError( iListenSocket->Accept( *iSocket ) );
+ iInitialized = ETrue;
+ TRACE_INFO( _L("CHSControlServer::Listen() status = OK" ) )
+
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::CancelListen()
+ {
+ TRACE_FUNC_ENTRY
+
+ if ( iState == EWaiting )//Client is connected to socket
+ {
+ iSocket->CancelAll();
+ // Return value may be ignored
+ iSocket->Shutdown( RSocket::EImmediate );
+ delete iSocket;
+ iSocket = NULL;
+ iListenSocket->CancelAll();
+
+ // Return value may be ignored
+ iListenSocket->Shutdown( RSocket::EImmediate );
+ delete iListenSocket;
+ iListenSocket = NULL;
+ }
+ else
+ { //Sockets are ready, but client is not connected
+ delete iSocket;
+ iSocket = NULL;
+ delete iListenSocket;
+ iListenSocket = NULL;
+ }
+
+ DeleteRecordSdp();
+
+ iInitialized = EFalse;
+ iState = ENone;
+
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::SetConnectionObserver(
+ MRemoteControllerConnectionObserver &aRemoteControllerObserver )
+ {
+ iConnectionObserver = &aRemoteControllerObserver;
+ }
+
+void CHsControlServer::HandleConnectCompleteL( TInt aErr )
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_INFO( ( _L("aErr = %d"), aErr) );
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::HandleAcceptCompleteL( TInt aErr )
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_INFO( ( _L("aErr = %d"), aErr) );
+ iState = EWaiting;
+ Receive();
+ if ( iConnectionObserver )
+ {
+ iConnectionObserver->HandleRemoteControllerConnected( aErr );
+ }
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::HandleShutdownCompleteL( TInt aErr )
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_INFO( ( _L("aErr = %d"), aErr) );
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::HandleSendCompleteL( TInt aErr )
+ {
+ TRACE_FUNC_ENTRY
+
+ TRACE_INFO( ( _L8("ControlServer sent %d bytes of data: [%S] with err [%d]")
+ ,iSendDataBuffer.Length(), &iSendDataBuffer, aErr) )
+
+ TInt error = KErrNone;
+
+ if ( aErr == KErrNone )
+ {
+ iSendDataBuffer.Zero();
+ if ( iTempDataBuffer.Length() > 0 )
+ {
+ iSendDataBuffer.Append( iTempDataBuffer );
+ iTempDataBuffer.Zero();
+ error = iSocket->Write( iSendDataBuffer );
+ }
+ }
+ Receive();
+
+ User::LeaveIfError( error );
+
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::HandleReceiveCompleteL( TInt aErr )
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_INFO( ( _L8("[ControlServer] received %d bytes of data: [%S]"
+ "with err [%d]"), iReceiveDataBuffer.Length(), &iReceiveDataBuffer,
+ aErr) )
+
+ if ( aErr == KErrNone )
+ {
+ TInt error = KErrNone;
+
+ if ( iSendDataBuffer.Length() > 0 )
+ {
+ error = iSocket->Write( iSendDataBuffer );
+ }
+ else if ( iTempDataBuffer.Length() > 0 )
+ {
+ iSendDataBuffer.Append( iTempDataBuffer );
+ iTempDataBuffer.Zero();
+ error = iSocket->Write( iSendDataBuffer );
+ }
+
+ TRAP_IGNORE( HandleRequestL( iReceiveDataBuffer ) );
+
+ Receive();
+
+ User::LeaveIfError( error );
+ }
+ else
+ {
+ TRACE_INFO( _L("ControlClient is disconnected") )
+
+ if ( iConnectionObserver )
+ {
+ iConnectionObserver->HandleRemoteControllerDisconnected( aErr );
+ }
+ CancelListen();
+ StartRemoteControlServerL();
+ }
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::HandleIoctlCompleteL( TInt /*aErr*/)
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::HandleActivateBasebandEventNotifierCompleteL(
+ TInt /*aErr*/, TBTBasebandEventNotification& /*aEventNotification*/)
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_FUNC_EXIT
+ }
+
+TInt CHsControlServer::Send( const TDesC8& aData )
+ {
+ TRACE_FUNC_ENTRY
+ TInt error = KErrNone;
+ if ( iState != EWaiting )
+ {
+ error = KErrNotReady;
+ TRACE_INFO( _L("ControlServer not ready") )
+
+ return error;
+ }
+
+ if ( iSendDataBuffer.Length() == 0 )
+ {
+ iSendDataBuffer.Append( iTempDataBuffer );
+ iTempDataBuffer.Zero();
+ iSendDataBuffer.Append( aData );
+ }
+ else
+ {
+ iTempDataBuffer.Append( aData );
+ }
+
+ if ( iSendDataBuffer.Length() > 0 )
+ {
+ iSocket->CancelRecv();
+ error = iSocket->Write( iSendDataBuffer );
+ Receive();
+ }
+ else
+ {
+ Receive();
+ }
+ TRACE_FUNC_EXIT
+ return error;
+ }
+
+void CHsControlServer::Receive()
+ {
+ TRACE_FUNC_ENTRY
+ // Return value may be ignored,
+ // error will be notified to HandleReceiveCompleteL
+ iSocket->RecvOneOrMore( iReceiveDataBuffer, 0, iDataLength );
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::RegisterSdpL( TInt aChannel )
+ {
+ TRACE_FUNC_ENTRY
+
+ User::LeaveIfError( iSdpServer.Connect() );
+ User::LeaveIfError( iSdpDB.Open( iSdpServer ) );
+
+ TUUID serviceUUID( KHsRemoteControlServiceID );
+ iSdpDB.CreateServiceRecordL( serviceUUID, iSdpRecordHandle );
+
+ CSdpAttrValueDES* valDES = CSdpAttrValueDES::NewDESL( NULL );
+ CleanupStack::PushL( valDES );
+ valDES->StartListL()->BuildDESL()->StartListL()->BuildUUIDL( TUUID(
+ KL2CAPUUID ) )->EndListL()->BuildDESL()->StartListL()->BuildUUIDL(
+ TUUID( KRFCommUUID ) )->BuildUintL(
+ TSdpIntBuf <TUint8> ( aChannel ) )->EndListL()->EndListL();
+
+ iSdpDB.UpdateAttributeL( iSdpRecordHandle,
+ KSdpAttrIdProtocolDescriptorList, *valDES );
+
+ CleanupStack::PopAndDestroy( valDES );
+
+ iSdpDB.UpdateAttributeL( iSdpRecordHandle, KSdpAttrIdBasePrimaryLanguage
+ + KSdpAttrIdOffsetServiceName, KServiceName );
+
+ iSdpDB.UpdateAttributeL( iSdpRecordHandle, KSdpAttrIdBasePrimaryLanguage
+ + KSdpAttrIdOffsetServiceDescription, KServiceDesc );
+
+ UpdateAvailabilityL( ETrue );
+
+ TRACE_INFO ( _L("CHsControlServer::RegisterSdpL, status = OK") )
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::UpdateAvailabilityL( TBool aAvailable )
+ {
+ TInt state = ( aAvailable ? KServicAvailable : KServiceUnavailable );
+ // Set availability
+ iSdpDB.UpdateAttributeL( iSdpRecordHandle, KSdpAttrIdServiceAvailability,
+ state );
+ // Mark record changed
+ iSdpDB.UpdateAttributeL( iSdpRecordHandle, KSdpAttrIdServiceRecordState,
+ ++iRecordState );
+ }
+
+void CHsControlServer::DeleteRecordSdp()
+ {
+ TRACE_FUNC_ENTRY
+
+ iSdpDB.DeleteRecord( iSdpRecordHandle );
+ iSdpRecordHandle = 0;
+ iSdpDB.Close();
+ iSdpServer.Close();
+
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::HandleRequestL( TDes8 &aRequest )
+ {
+ TRACE_FUNC_ENTRY
+
+ TBuf8 <KHsRemoteControlPackageLength> buf;
+
+ THsControlCommandData dummyBuf( KNullDesC8 );
+ THsRemoteControlCommand command( dummyBuf, EHsLast );
+ if ( iDataHandler )
+ {
+ TInt err = iDataHandler->RecognizeCommand( aRequest, command );
+ if ( KErrNone != err )
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+
+ THsRemoteControlCommandType type = EHsLast;
+ command.GetType( type );
+
+ switch ( type )
+ {
+ case EHsTurnOn:
+ {
+ command.GetData( buf );
+
+ RBuf8 cod;
+ RBuf8 sdp;
+ RBuf8 plugin;
+
+ cod.CleanupClosePushL();
+ sdp.CleanupClosePushL();
+ plugin.CleanupClosePushL();
+
+ RetrieveStartupParamsL( buf, cod, sdp, plugin );
+
+ iHsCore->StartSimulationL( cod, sdp, plugin );
+
+ CleanupStack::PopAndDestroy( 3 );
+ }
+ break;
+
+ case EHsTurnOff:
+ {
+ iHsCore->StopSimulation();
+ }
+ break;
+ case EHsConnectLastconnected:
+ {
+ iHsCore->ConnectWithLastConnectedL();
+ }
+ break;
+ case EHsConnectDevAddress:
+ {
+ command.GetData( buf );
+ iHsCore->ConnectWithDevAddress( buf.Expand() );
+ }
+ break;
+ case EHsConnectName:
+ {
+ command.GetData( buf );
+ iHsCore->ConnectWithName( buf.Expand() );
+ }
+ break;
+ case EHsDisconnectAGs:
+ {
+ iHsCore->DisconnectClients();
+ }
+ break;
+ case EHsAcceptCall:
+ {
+ User::LeaveIfError( iHsCore->AcceptIncomingCall() );
+ }
+ break;
+ case EHsReleaseCall:
+ {
+ User::LeaveIfError( iHsCore->ReleaseOngoingCall() );
+ }
+ break;
+
+ case EHsSetSpeakerVolume:
+ {
+ command.GetData( buf );
+ RBuf8 tempBuf;
+ tempBuf.CreateL( buf.Length() + KHsATCommandEnding().Length()
+ + KHsATVGS().Length() );
+ tempBuf.Copy( KHsATVGS );
+ tempBuf.Append( buf );
+ tempBuf.Append( KHsATCommandEnding );
+
+ iHsCore->Send( tempBuf );
+ tempBuf.Close();
+
+ }
+ break;
+ case EHsSetMicVolume:
+ {
+ command.GetData( buf );
+ RBuf8 tempBuf;
+ tempBuf.CreateL( buf.Length() + KHsATCommandEnding().Length()
+ + KHsATVGM().Length() );
+ tempBuf.Copy( KHsATVGM );
+ tempBuf.Append( buf );
+ tempBuf.Append( KHsATCommandEnding );
+
+ iHsCore->Send( tempBuf );
+ tempBuf.Close();
+ }
+ break;
+ case EHsSendAnyAt:
+ {
+ command.GetData( buf );
+ User::LeaveIfError( iHsCore->Send( buf ) );
+ }
+ break;
+ default:
+ User::Leave( KErrArgument );
+
+ }
+ TRACE_FUNC_EXIT
+ }
+
+void CHsControlServer::RetrieveStartupParamsL( const TDesC8& aParams,
+ RBuf8& aPluginCod, RBuf8& aPluginSdp, RBuf8& aPluginProfile )
+
+ {
+ TRACE_FUNC_ENTRY
+
+ TInt sepPos = aParams.Find( KHsRemoteRequestParamSeparator );
+
+ User::LeaveIfError( sepPos );
+
+ aPluginCod.CreateL( aParams.Left( sepPos ) );
+
+ sepPos += 2;
+
+ TInt sepPos2 = aParams.Mid( sepPos, aParams.Length() - sepPos ).Find(
+ KHsRemoteRequestParamSeparator );
+
+ User::LeaveIfError( sepPos2 );
+
+ aPluginSdp.CreateL( aParams.Mid( sepPos, sepPos2 ) );
+
+ sepPos += 2;
+ sepPos += sepPos2;
+
+ aPluginProfile.CreateL( aParams.Mid( sepPos, aParams.Length() - sepPos ) );
+
+ TRACE_FUNC_EXIT
+ }