bluetoothengine/headsetsimulator/remotecontroller/src/hsremotecontroller.cpp
author michal.sulewski
Wed, 15 Sep 2010 15:59:44 +0200
branchheadsetsimulator
changeset 60 90dbfc0435e3
permissions -rw-r--r--
source code commit

/*
 * 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 "hsremotecontroller.h"
#include "hsrcbttools.h"
#include "hsrccommand.h"
#include "debug.h"

EXPORT_C CHsRemoteController* CHsRemoteController::NewL(
        MHsRCObserver* aObserver )
    {
    CHsRemoteController* self = CHsRemoteController::NewLC( aObserver );
    CleanupStack::Pop( self );
    return self;
    }

EXPORT_C CHsRemoteController* CHsRemoteController::NewLC(
        MHsRCObserver* aObserver )
    {
    CHsRemoteController* self = new ( ELeave ) CHsRemoteController( aObserver );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }

EXPORT_C CHsRemoteController::~CHsRemoteController()
    {
    TRACE_FUNC_ENTRY
    if ( iBTManager )
        {
        delete iBTManager;
        }

    if ( iSocket )
        {
        if ( iConnected )
            {
            iSocket->CancelAll();
            // Return value may be ignored
            iSocket->Shutdown( RSocket::EImmediate );
            }
        delete iSocket;
        }

    iSocketServ.Close();

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ConnectHsDevAddrL(
        const TBTDevAddr& aDevAddr, const TUUID& aService )
    {
    TRACE_FUNC_ENTRY
    if ( iConnected )
        {
        User::Leave( KErrInUse );
        }
    if ( iObserver )
        {
        iObserver->HandleConnectingToHs();
        }
    iBTManager->SetService( aService );

    iBTManager->ConnectDevAddrL( aDevAddr );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ConnectHsDevNameL( const TDesC& aHsName,
        const TUUID& aService )
    {
    TRACE_FUNC_ENTRY
    if ( iConnected )
        {
        User::Leave( KErrInUse );
        }
    if ( iObserver )
        {
        iObserver->HandleConnectingToHs();
        }
    iBTManager->SetService( aService );
    iBTManager->ConnectDevNameL( aHsName );

    TRACE_FUNC_EXIT

    }

EXPORT_C void CHsRemoteController::CancelConnectingToHs()
    {
    TRACE_FUNC_ENTRY
    if ( iBTManager )
        {
        iBTManager->CancelConnecting();
        }
    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::DisconnectFromHs()
    {
    TRACE_FUNC_ENTRY
    if ( iSocket )
        {
        if ( iConnected )
            {
            iSocket->CancelAll();
            // Return value may be ignored
            iSocket->Shutdown( RSocket::EImmediate );
            }
        delete iSocket;
        iSocket = NULL;
        iConnected = EFalse;
        if ( iObserver )
            {
            iObserver->HandleDisconnectedFromHs( KErrNone );
            }

        }

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ReqTurnOnHs( const TDesC& aPluginCod,
        const TDesC& aPluginSdp, const TDesC& aPluginProfile )
    {
    TRACE_FUNC_ENTRY

    __ASSERT_ALWAYS( iConnected,
            User::Panic(KHSRemoteControllerNotConnectedPanicMsg, KErrNotReady));

    RBuf buf;
    TRAPD(err, buf.CreateL( aPluginCod.Length() + aPluginSdp.Length()
                    + aPluginProfile.Length() + 4 ) );
    if ( err == KErrNone )
        {
        TBuf <2> sep;
        CnvUtfConverter::ConvertToUnicodeFromUtf8( sep,
                KHsRemoteRequestParamSeparator );

        buf.Copy( aPluginCod );
        buf.Append( sep );
        buf.Append( aPluginSdp );
        buf.Append( sep );
        buf.Append( aPluginProfile );

        SendRequest( EHsTurnOn, buf );
        }

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ReqTurnOffHs()
    {
    TRACE_FUNC_ENTRY

    __ASSERT_ALWAYS( iConnected,
            User::Panic(KHSRemoteControllerNotConnectedPanicMsg, KErrNotReady));

    SendRequest( EHsTurnOff );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ReqConnectWithDevAddr(
        const TBTDevAddr& aDevAddr )
    {
    TRACE_FUNC_ENTRY

    __ASSERT_ALWAYS( iConnected, 
            User::Panic(KHSRemoteControllerNotConnectedPanicMsg, KErrNotReady));

    TBuf <KDevAddrLength> devAddrBuf;
    aDevAddr.GetReadable( devAddrBuf );
    SendRequest( EHsConnectDevAddress, devAddrBuf );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ReqConnectWithDevName( 
        const TDesC& aDevName )
    {
    TRACE_FUNC_ENTRY

    __ASSERT_ALWAYS( iConnected, 
            User::Panic(KHSRemoteControllerNotConnectedPanicMsg, KErrNotReady));
    SendRequest( EHsConnectName, aDevName );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ReqConnectWithLastConnected()
    {
    TRACE_FUNC_ENTRY

    __ASSERT_ALWAYS( iConnected,
            User::Panic(KHSRemoteControllerNotConnectedPanicMsg, KErrNotReady));
    
    SendRequest( EHsConnectLastconnected );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ReqAcceptCall()
    {
    TRACE_FUNC_ENTRY

    __ASSERT_ALWAYS( iConnected, 
            User::Panic(KHSRemoteControllerNotConnectedPanicMsg, KErrNotReady));
    SendRequest( EHsAcceptCall );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ReqReleaseCall()
    {
    TRACE_FUNC_ENTRY

    __ASSERT_ALWAYS( iConnected, 
            User::Panic(KHSRemoteControllerNotConnectedPanicMsg, KErrNotReady));
    SendRequest( EHsReleaseCall );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ReqSetMicGain( const TDesC& aValue )
    {
    TRACE_FUNC_ENTRY

    __ASSERT_ALWAYS( iConnected, 
            User::Panic(KHSRemoteControllerNotConnectedPanicMsg, KErrNotReady));
    SendRequest( EHsSetMicVolume, aValue );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ReqSetSpeakerVolume( const TDesC& aValue )
    {
    TRACE_FUNC_ENTRY

    __ASSERT_ALWAYS( iConnected, 
            User::Panic(KHSRemoteControllerNotConnectedPanicMsg, KErrNotReady));
    
    SendRequest( EHsSetSpeakerVolume, aValue );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ReqSendAnyAt( const TDesC& aValue )
    {
    TRACE_FUNC_ENTRY

    __ASSERT_ALWAYS( iConnected, 
            User::Panic(KHSRemoteControllerNotConnectedPanicMsg, KErrNotReady));
    SendRequest( EHsSendAnyAt, aValue );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsRemoteController::ReqDisconnectAG()
    {
    TRACE_FUNC_ENTRY

    __ASSERT_ALWAYS( iConnected, 
            User::Panic(KHSRemoteControllerNotConnectedPanicMsg, KErrNotReady));
    SendRequest( EHsDisconnectAGs );

    TRACE_FUNC_EXIT
    }

CHsRemoteController::CHsRemoteController( MHsRCObserver* aObserver ) :
    iObserver( aObserver )
    {

    }

void CHsRemoteController::ConstructL()
    {
    User::LeaveIfError( iSocketServ.Connect() );
    User::LeaveIfError( CreateBTManager() );
    }

void CHsRemoteController::SendRequest(
        const THsRemoteControlCommandType aCommandType, const TDesC& aData )
    {
    TRACE_FUNC_ENTRY

    THsRCCommandData data( KNullDesC8 );
    TInt err = CnvUtfConverter::ConvertFromUnicodeToUtf8( data, aData );
    if ( err == KErrNone )
        {
        THsRCCommand cmd( data, aCommandType );
        cmd.ToDes8( iSendDataBuffer );

        err = Send( iSendDataBuffer );
        if ( ( err == KErrNone ) && iObserver )
            {
            iObserver->HandleRequestSent( aCommandType );
            }
        }
    TRACE_FUNC_EXIT
    }

TInt CHsRemoteController::Send( const TDesC8& aData )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( ( _L8("Data to be send: [%S]"), &aData) )

    if ( !iConnected )
        {
        TRACE_INFO( _L("Not connected to HS") )
        TRACE_FUNC_EXIT
        return KErrNotReady;
        }

    iSendDataBuffer.Copy( aData );
    if ( iSendDataBuffer.Length() > 0 )
        {
        TInt err = iSocket->Write( iSendDataBuffer );
        if ( err == KErrNone )
            {
            iSendDataBuffer.Zero();
            }

        TRACE_FUNC_EXIT
        return err;
        }

    TRACE_FUNC_EXIT

    return KErrNone;
    }

void CHsRemoteController::Receive()
    {
    TRACE_FUNC_ENTRY
    // Return value may be ignored, 
    // error will be notified to HandleReceiveCompleteL
    iSocket->RecvOneOrMore( iReceiveDataBuffer, 0, iDataLength );
    TRACE_FUNC_EXIT
    }

TInt CHsRemoteController::ConnectRemoteControlServer( const TBTDevAddr& aAddr,
        const TInt aPort )
    {
    TRACE_FUNC_ENTRY
    TInt error = KErrNone;
    if ( !iConnected )
        {

        TProtocolDesc protocolDesc;
        error = iSocketServ.FindProtocol( _L("RFCOMM"), protocolDesc );
        if ( error != KErrNone )
            {
            TRACE_INFO( ( _L("iSocketServ.FindProtocol error = %d"), error) )
            TRACE_FUNC_EXIT
            return error;
            }

        TRAP(error, iSocket = CBluetoothSocket::NewL(*this, iSocketServ,
                        protocolDesc.iSockType, protocolDesc.iProtocol));
        if ( error != KErrNone )
            {
            TRACE_INFO( ( _L("iSocket = CBluetoothSocket::NewL error = %d"), error))
            TRACE_FUNC_EXIT
            return error;
            }

        TBTSockAddr addr;
        addr.SetBTAddr( aAddr );
        addr.SetPort( aPort );
        error = iSocket->Connect( addr );

        if ( error != KErrNone )
            {
            TRACE_INFO( ( _L("iSocket->Connect error = %d"), error))
            TRACE_FUNC_EXIT
            return error;
            }
        }
    else
        {
        TRACE_INFO( _L("CHsRemoteController::Connect() - client is already connected") )
        TRACE_FUNC_EXIT
        return KErrInUse;
        }

    TRACE_FUNC_EXIT
    return KErrNone;
    }

TInt CHsRemoteController::CreateBTManager()
    {
    TInt err = KErrNone;

    if ( !iBTManager )
        {
        TRAP(err, iBTManager = CHsRCBTManager::NewL(iSocketServ, this));
        if ( err != KErrNone )
            {
            iBTManager = NULL;
            }
        return err;
        }
    else
        {
        return KErrAlreadyExists;
        }

    }

void CHsRemoteController::HandleConnectCompleteL( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( ( _L("aErr = %d"), aErr) )

    if ( aErr == KErrNone )
        {
        TRACE_INFO(_L("Connect completed"))
        iConnected = ETrue;
        Receive();
        }
    if ( iObserver )
        {
        iObserver->HandleConnectedToHs( aErr );
        }
    TRACE_FUNC_EXIT
    }

void CHsRemoteController::HandleAcceptCompleteL( TInt /*aErr*/)
    {
    }

void CHsRemoteController::HandleShutdownCompleteL( TInt /*aErr*/)
    {
    }

void CHsRemoteController::HandleSendCompleteL( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( ( _L("aErr = %d"), aErr) )

    if ( aErr == KErrNone )
        {
        if ( ( iSendDataBuffer.Length() > 0 ) && ( ( iSocket->Write(
                iSendDataBuffer ) ) == KErrNone ) )
            {
            iSendDataBuffer.Zero();
            }
        }
    Receive();
    TRACE_FUNC_EXIT
    }

void CHsRemoteController::HandleReceiveCompleteL( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( ( _L("aErr = %d"), aErr) )

    if ( aErr == KErrNone )
        {
        if ( ( iSendDataBuffer.Length() > 0 ) && ( ( iSocket->Write(
                iSendDataBuffer ) ) == KErrNone ) )
            {
            iSendDataBuffer.Zero();
            }
        Receive();
        }
    else
        {
        TRACE_INFO(_L("ControlServer cancelled listening"));
        DisconnectFromHs();
        }
    }

void CHsRemoteController::HandleIoctlCompleteL( TInt /*aErr*/)
    {
    }

void CHsRemoteController::HandleActivateBasebandEventNotifierCompleteL(
        TInt /*aErr*/, TBTBasebandEventNotification& /*aEventNotification*/)
    {
    }

void CHsRemoteController::HandleDesiredDevFound( const TDesC& aDevName,
        const TBTDevAddr& aDevAddr, const TInt aPort )
    {
    TRACE_FUNC_ENTRY
    //value ignored
    TInt err = ConnectRemoteControlServer( aDevAddr, aPort );

    TRACE_INFO((_L("err = %d"), err))

    if ( iObserver && err != KErrNone )
        {
        iObserver->HandleConnectedToHs( err );
        }
    TRACE_FUNC_EXIT
    }

void CHsRemoteController::HandleDesiredDevNotFound( TInt aErr )
    {
    TRACE_FUNC_ENTRY

    if ( iObserver )
        {
        iObserver->HandleConnectedToHs( aErr );
        }

    TRACE_FUNC_EXIT
    }