bluetoothengine/headsetsimulator/core/src/RemoteControl/hsremotecontrolserver.cpp
branchheadsetsimulator
changeset 60 90dbfc0435e3
--- /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
+    }