bluetoothengine/headsetsimulator/core/src/hscore.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 "hscore.h"
#include "hsprofilemanager.h"
#include "hsobserver.h"
#include "hsserver.h"
#include "hsaudioserver.h"
#include "hsclientmanager.h"
#include "hsclient.h"
#include "hstools.h"
#include "hsremotecontrolserver.h"
#include "debug.h"

EXPORT_C CHsCore* CHsCore::NewL( const TUUID& aService )
    {
    CHsCore* self = CHsCore::NewLC( aService );
    CleanupStack::Pop( self );
    return self;
    }

EXPORT_C CHsCore* CHsCore::NewLC( const TUUID& aService )
    {
    CHsCore* self = new ( ELeave ) CHsCore( aService );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }

EXPORT_C CHsCore::~CHsCore()
    {
    TRACE_FUNC_ENTRY

    DestroyComponents();
    iSocketServ.Close();

    TRACE_FUNC_EXIT
    }

CHsCore::CHsCore( const TUUID& aService ) :
    iService( aService )
    {

    }

void CHsCore::ConstructL()
    {
    TRACE_FUNC_ENTRY

    User::LeaveIfError( iSocketServ.Connect() );
    CreateComponentsL();
    RegisterProperty();
    InitializeSimulationL();
    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsCore::StartSimulationL( const TUid& aCoDUid,
        const TUid& aSdpUid, const TUid& aProfileUid, const TDesC& aBTName )
    {
    TRACE_FUNC_ENTRY

    InitializeSimulationL( aBTName );

    LoadSdpL( aSdpUid );
    LoadCodL( aCoDUid );
    LoadProfileL( aProfileUid );

    User::LeaveIfError( StartHSServer() );
    User::LeaveIfError( StartAudioServer( ETrue ) );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsCore::StartSimulationL( const TDesC8& aCoDName,
        const TDesC8& aSdpName, const TDesC8& aProfileName,
        const TDesC& aBTName )
    {
    TRACE_FUNC_ENTRY

    InitializeSimulationL( aBTName );

    LoadSdpL( aSdpName );
    LoadCodL( aCoDName );
    LoadProfileL( aProfileName );

    User::LeaveIfError( StartHSServer() );
    User::LeaveIfError( StartAudioServer( ETrue ) );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsCore::StopSimulation()
    {
    TRACE_FUNC_ENTRY
    DestroyPluginManager();
    DestroyClientManager();
    DestroyHSServer();
    DestroyAudioServer();

    CreateHSServer();
    CreateAudioServer( ETrue );
    CreateClientManager();
    CreatePluginManager();

    TRAP_IGNORE(InitializeSimulationL());
    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsCore::ConnectWithName( const TDesC &aName )
    {
    TRACE_FUNC_ENTRY
    if ( iObserver )
        {
        iObserver->HandleConnectingToClient();
        }
    if ( iHsBTManager )
        {
        TRAPD(err, iHsBTManager->FindNameL(aName));
        if ( err != KErrNone && iObserver )
            {
            iObserver->HandleUnableToConnectClient();
            }
        TRACE_INFO((_L("Connect with name: %S, error = %d"), &aName, err))
        }
    else if ( iObserver )
        {
        iObserver->HandleUnableToConnectClient();
        }
    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsCore::ConnectWithDevAddress( const TDesC& aDevAddress )
    {
    TRACE_FUNC_ENTRY
    if ( iObserver )
        {
        iObserver->HandleConnectingToClient();
        }
    if ( iHsBTManager )
        {
        TRAPD(err, iHsBTManager->FindDevL(aDevAddress));
        if ( err != KErrNone && iObserver )
            {
            iObserver->HandleUnableToConnectClient();
            }
        }
    else if ( iObserver )
        {
        iObserver->HandleUnableToConnectClient();
        }
    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsCore::ConnectWithLastConnectedL()
    {
    TRACE_FUNC_ENTRY

    TBTDevAddr addr;
    User::LeaveIfError( GetLastConnected( addr ) );

    RBuf lastDevAddrBuf;

    lastDevAddrBuf.CreateL( KMaxBluetoothNameLen );
    addr.GetReadable( lastDevAddrBuf );

    ConnectWithDevAddress( lastDevAddrBuf );

    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsCore::CancelConnecting()
    {
    TRACE_FUNC_ENTRY
    if ( iHsBTManager )
        {
        iHsBTManager->CancelConnecting();
        }
    TRACE_FUNC_EXIT
    }

EXPORT_C void CHsCore::DisconnectClients()
    {
    TRACE_FUNC_ENTRY
    if ( iHSClientManager )
        {
        iHSClientManager->DisconnectClients();
        }
    TRACE_FUNC_EXIT
    }

EXPORT_C TInt CHsCore::Send( const TDesC8 &aData, TInt aNumber )
    {
    TRACE_FUNC_ENTRY
    TInt ret = KErrNone;
    if ( iHSClientManager && iHSProfileManager )
        {
        TBuf8 <KHsClientBufferLength> tmp;

        TRAP(ret, iHSProfileManager->HandleCommandL(aData, tmp, EFalse));
        if ( KErrNone == ret )
            {
            ret = iHSClientManager->Send( tmp, aNumber );
            }
        }
    else
        {
        ret = KErrNotReady;
        }
    TRACE_FUNC_EXIT
    return ret;
    }

EXPORT_C void CHsCore::SetObserver( MHsObserver& aObserver )
    {
    TRACE_FUNC_ENTRY
    iObserver = &aObserver;
    TRACE_FUNC_EXIT
    }

EXPORT_C TInt CHsCore::AcceptIncomingCall()
    {
    TRACE_FUNC_ENTRY

    TBuf8 <KHsClientBufferLength> tmp;
    TRAPD(ret,iHSProfileManager->AcceptIncomingCallL(tmp));

    if ( KErrNone == ret )
        {
        ret = iHSClientManager->Send( tmp );
        }

    TRACE_FUNC_EXIT
    return ret;
    }

EXPORT_C TInt CHsCore::ReleaseOngoingCall()
    {
    TBuf8 <KHsClientBufferLength> tmp;
    TRAPD(ret,iHSProfileManager->ReleaseOngoingCallL(tmp));

    if ( KErrNone == ret )
        {
        ret = iHSClientManager->Send( tmp );
        }

    TRACE_FUNC_EXIT
    return ret;
    }

void CHsCore::InitializeSimulationL( const TDesC& aBTName )
    {
    TRACE_FUNC_ENTRY

    User::LeaveIfNull( iHsBTManager );
    if ( aBTName != KNullDesC )
        {
        SetBTName( aBTName );
        iHsBTManager->TurnBtOnL( aBTName );
        }
    else
        {
        iHsBTManager->TurnBtOnL();
        }

    TRACE_FUNC_EXIT
    }

void CHsCore::RegisterProperty()
    {
    TRACE_FUNC_ENTRY
    // Return value may be ignored, no influence on main Headset functionality
    RProperty::Define( KHSProperty, ELastDevice, RProperty::EByteArray,
            KLastDevAddrLength );

    TRACE_FUNC_EXIT
    }

void CHsCore::CreateComponentsL()
    {
    TRACE_FUNC_ENTRY
    User::LeaveIfError( CreateControlServer() );
    User::LeaveIfError( CreateHSServer() );
    User::LeaveIfError( CreateAudioServer( ETrue ) );
    User::LeaveIfError( CreateClientManager() );
    User::LeaveIfError( CreatePluginManager() );
    User::LeaveIfError( CreateBTManager() );

    TRACE_FUNC_EXIT
    }

void CHsCore::DestroyComponents()
    {
    TRACE_FUNC_ENTRY

    DestroyControlServer();
    DestroyPluginManager();
    DestroyClientManager();
    DestroyHSServer();
    DestroyAudioServer();
    DestroyBTManager();

    TRACE_FUNC_EXIT
    }

TInt CHsCore::CreateHSServer()
    {
    TRACE_FUNC_ENTRY
    TInt ret = KErrNone;

    if ( !iHSServer )
        {
        TRAP(ret, iHSServer = CHsServer::NewL(iSocketServ));

        if ( ret == KErrNone )
            {
            iHSServer->SetNewClientObserver( *this );
            }
        }
    else
        {
        ret = KErrAlreadyExists;
        }

    TRACE_FUNC_EXIT
    return ret;
    }

TInt CHsCore::StartHSServer()
    {
    TRACE_FUNC_ENTRY

    TInt ret = KErrNone;
    if ( !iHSServer )
        {
        ret = KErrNotReady;
        }
    else
        {
        if ( !iHSServer->IsReady() )
            {
            ret = iHSServer->Listen();
            }
        else
            {
            ret = KErrInUse;
            }
        }

    if ( ret == KErrNone && iHSProfileManager )
        {
        iHSProfileManager->SetSdpServicePort( iHSServer->GetPort() );
        iHSProfileManager->RefreshSdp();
        }

    TRACE_FUNC_EXIT
    return ret;
    }

void CHsCore::StopHSServer()
    {
    TRACE_FUNC_ENTRY
    if ( ( iHSServer ) && ( iHSServer->IsReady() ) )
        {
        iHSServer->Shutdown();
        }

    TRACE_FUNC_EXIT
    }

void CHsCore::DestroyHSServer()
    {
    TRACE_FUNC_ENTRY

    if ( iHSServer )
        {
        delete iHSServer;
        iHSServer = NULL;
        }
    TRACE_FUNC_EXIT
    }

TInt CHsCore::CreateAudioServer( TBool aPullAudio )
    {
    TRACE_FUNC_ENTRY

    TInt ret = KErrNone;

    if ( iAudioServer )
        {
        ret = KErrAlreadyExists;
        }
    else
        {
        TRAP(ret, iAudioServer = CHsAudioServer::NewL(iSocketServ, aPullAudio));
        }

    TRACE_FUNC_EXIT

    return ret;
    }

TInt CHsCore::StartAudioServer( TBool aPullAudio )
    {
    TRACE_FUNC_ENTRY
    TInt ret = KErrNone;

    if ( iAudioServer && !iAudioServer->IsListen()
            && !iAudioServer->IsConnected() )
        {
        iAudioServer->SetPullAudio( aPullAudio );
        TRAP(ret, iAudioServer->ListenL());
        }
    else
        {
        ret = KErrNotReady;
        }

    TRACE_FUNC_EXIT

    return ret;

    }

void CHsCore::StopAudioServer()
    {
    TRACE_FUNC_ENTRY
    if ( iAudioServer )
        {
        if ( iAudioServer->IsConnected() )
            {
            iAudioServer->Disconnect();
            }
        if ( iAudioServer->IsListen() )
            {
            iAudioServer->Shutdown();
            }
        }
    TRACE_FUNC_EXIT
    }

void CHsCore::DestroyAudioServer()
    {
    TRACE_FUNC_ENTRY

    if ( iAudioServer )
        {
        delete iAudioServer;
        iAudioServer = NULL;
        }
    TRACE_FUNC_EXIT
    }

TInt CHsCore::CreateClientManager()
    {
    TRACE_FUNC_ENTRY
    TInt err = KErrNone;

    if ( iHSClientManager )
        {
        err = KErrAlreadyExists;
        }
    else
        {
        TRAP(err, iHSClientManager = CHsClientManager::NewL());
        }
    TRACE_FUNC_EXIT
    return err;
    }

void CHsCore::DestroyClientManager()
    {
    TRACE_FUNC_ENTRY
    if ( iHSClientManager )
        {
        delete iHSClientManager;
        iHSClientManager = NULL;
        }
    TRACE_FUNC_EXIT
    }

TInt CHsCore::CreatePluginManager()
    {
    TRACE_FUNC_ENTRY
    TInt err = KErrNone;
    if ( iHSProfileManager )
        {
        err = KErrAlreadyExists;
        }
    else
        {
        TRAP(err, iHSProfileManager = CHsProfileManager::NewL());
        }
    TRACE_FUNC_EXIT
    return err;
    }

void CHsCore::DestroyPluginManager()
    {
    TRACE_FUNC_ENTRY

    if ( iHSProfileManager )
        {
        delete iHSProfileManager;
        iHSProfileManager = NULL;
        }

    TRACE_FUNC_EXIT
    }

TInt CHsCore::CreateBTManager()
    {
    TRACE_FUNC_ENTRY
    TInt err = KErrNone;

    if ( !iHsBTManager )
        {
        TRAP(err, iHsBTManager = CHsBTManager::NewL(iSocketServ, this));
        if ( err == KErrNone )
            {
            iHsBTManager->SetService( iService );
            }
        }
    else
        {
        err = KErrAlreadyExists;
        }

    TRACE_FUNC_EXIT
    return err;
    }

void CHsCore::DestroyBTManager()
    {
    TRACE_FUNC_ENTRY
    if ( iHsBTManager )
        {
        delete iHsBTManager;
        iHsBTManager = NULL;
        }
    TRACE_FUNC_EXIT
    }

TInt CHsCore::CreateControlServer()
    {
    TRACE_FUNC_ENTRY
    TInt err = KErrNone;
    if ( !iHSControlServer )
        {
        TRAP(err, iHSControlServer = CHsControlServer::NewL(iSocketServ, this);
                iHSControlServer->SetConnectionObserver( *this );
                iHSControlServer->StartRemoteControlServerL());
        }
    else
        {
        err = KErrAlreadyExists;
        }
    TRACE_FUNC_EXIT
    return err;
    }

void CHsCore::DestroyControlServer()
    {
    TRACE_FUNC_ENTRY
    if ( iHSControlServer )
        {
        delete iHSControlServer;
        iHSControlServer = NULL;
        }
    TRACE_FUNC_EXIT

    }

void CHsCore::SetBTName( const TBTFriendlyName &aBTName )
    {
    iBTFriendlyName = aBTName;
    }

TInt CHsCore::GetLastConnected( TBTDevAddr &aBTDevAddr )
    {
    TRACE_FUNC_ENTRY
    RBuf bufAddr;
    TInt error = bufAddr.Create( KLastDevAddrLength );
    if ( KErrNone != error )
        {

        return error;
        }

    error = RProperty::Get( KHSProperty, ELastDevice, bufAddr );
    TRACE_INFO( (_L("Last-connected dev addr: %S"), &bufAddr) )
    if ( error == KErrNone )
        {
        error = aBTDevAddr.SetReadable( bufAddr );

        }
    bufAddr.Close();
    TRACE_FUNC_EXIT
    return error;
    }

TInt CHsCore::SaveClient( CBluetoothSocket* aSocket )
    {
    TRACE_FUNC_ENTRY
    TInt error = KErrNone;
    TBTSockAddr sockAddr;
    aSocket->RemoteName( sockAddr );

    TBTDevAddr devAddr = sockAddr.BTAddr();

    RBuf bufAddr;

    error = bufAddr.Create( KLastDevAddrLength );
    if ( KErrNone == error )
        {
        devAddr.GetReadable( bufAddr );
        TRACE_INFO( (_L("Read address:: %S"), &bufAddr) );
        error = RProperty::Set( KHSProperty, ELastDevice, bufAddr );
        bufAddr.Close();
        }

    TRACE_FUNC_EXIT
    return error;
    }

void CHsCore::SetSdpRecordServicePortFromServer()
    {
    TRACE_FUNC_ENTRY
    if ( iHSServer && iHSProfileManager )
        {
        iHSProfileManager->SetSdpServicePort( iHSServer->GetPort() );
        }
    TRACE_FUNC_EXIT
    }

void CHsCore::LoadProfileL( const TDesC8& aProfileName )
    {
    TRACE_FUNC_ENTRY

    User::LeaveIfNull( iHSProfileManager );
    iHSProfileManager->LookupAndManageProfileL( aProfileName );

    TRACE_FUNC_EXIT
    }

void CHsCore::LoadProfileL( const TUid& aProfileUid )
    {
    TRACE_FUNC_ENTRY

    User::LeaveIfNull( iHSProfileManager );
    iHSProfileManager->LookupAndManageProfileL( aProfileUid );

    TRACE_FUNC_EXIT
    }

void CHsCore::LoadSdpL( const TDesC8& aSdpName )
    {
    TRACE_FUNC_ENTRY

    User::LeaveIfNull( iHSProfileManager );

    SetSdpRecordServicePortFromServer();
    iHSProfileManager->LookupAndManageSdpL( aSdpName );
    TRACE_INFO(_L("iHSProfileManager lookup and manage SDP success") );

    iHSProfileManager->LoadSdpL();

    TRACE_FUNC_EXIT
    }

void CHsCore::LoadSdpL( const TUid& aSdpUid )
    {
    TRACE_FUNC_ENTRY
    User::LeaveIfNull( iHSProfileManager );

    SetSdpRecordServicePortFromServer();
    iHSProfileManager->LookupAndManageSdpL( aSdpUid );
    TRACE_INFO(_L("iHSProfileManager lookup and manage SDP success") );

    iHSProfileManager->LoadSdpL();

    TRACE_FUNC_EXIT
    }

void CHsCore::LoadCodL( const TDesC8& aCoDName )
    {
    TRACE_FUNC_ENTRY

    User::LeaveIfNull( iHSProfileManager );

    iHSProfileManager->LookupAndManageCodL( aCoDName );
    iHSProfileManager->LoadCodL();

    TRACE_FUNC_EXIT
    }

void CHsCore::LoadCodL( const TUid& aCoDUid )
    {
    TRACE_FUNC_ENTRY

    User::LeaveIfNull( iHSProfileManager );

    iHSProfileManager->LookupAndManageCodL( aCoDUid );
    iHSProfileManager->LoadCodL();

    TRACE_FUNC_EXIT
    }

void CHsCore::HandleNewClientL( CBluetoothSocket* aClientSocket, TInt aErr )
    {
    TRACE_FUNC_ENTRY

    if ( ( KErrNone == aErr ) && ( iHSClientManager ) )
        {
        CHsClient *clientTmp = NULL;
        if ( aClientSocket )
            {
            clientTmp = CHsClient::NewL( aClientSocket, this, iHSClientManager );

            //Return value may be ignored
            SaveClient( aClientSocket );
            iHSClientManager->HandleNewClientL( clientTmp, aErr );

            TBuf8 <KHsClientBufferLength> tmp;

            iHSProfileManager->HandleClientConnected( tmp );
            if ( tmp.Compare( KNullDesC8 ) != 0 )
                {
                iHSClientManager->Send( tmp, KHsDefaultClientNumber );
                }

            if ( iObserver )
                {
                iObserver->HandleConnectedToClient();
                }
            }
        }
    else
        {
        if ( iHsBTManager )
            {
            iHsBTManager->CancelConnecting();
            }
        if ( iObserver )
            {
            iObserver->HandleUnableToConnectClient();
            }
        }

    TRACE_FUNC_EXIT
    }

void CHsCore::HandleClientConnectL( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( (_L("aErr = %d"), aErr))

    TRACE_FUNC_EXIT
    }

void CHsCore::HandleClientDisconnectL( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( (_L("aErr = %d"), aErr))

    if ( iObserver )
        {
        iObserver->HandleDisconnectedFromClient();
        }
    if ( iAudioServer )
        {
        iAudioServer->ListenL();
        }
    if ( iHSProfileManager )
        {
        iHSProfileManager->HandleClientDisconnected( aErr );
        }

    TRACE_FUNC_EXIT
    }

void CHsCore::HandleClientReceiveCompleteL( const TDesC8 &aData, TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( (_L("aErr = %d"), aErr))

    if ( iHSProfileManager )
        {
        iBufferFromProfileToClient.Zero();

        TRACE_INFO( (_L8(" Received data from AG client [%S]") , &aData) )
        iHSProfileManager->HandleCommandL( aData, iBufferFromProfileToClient,
                ETrue );

        if ( iHSClientManager )
            {
            iHSClientManager->Send( iBufferFromProfileToClient );
            }
        }
    TRACE_FUNC_EXIT
    }
void CHsCore::HandleClientSendCompleteL( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( (_L("aErr = %d"), aErr))

    TRACE_FUNC_EXIT
    }

void CHsCore::HandleClientOtherProblemL( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( (_L("aErr = %d"), aErr))

    TRACE_FUNC_EXIT
    }

void CHsCore::HandleDesiredDeviceFound( const TDesC& /*aDevName*/,
        const TBTDevAddr& aDevAddr, const TInt aPort )
    {
    TRACE_FUNC_ENTRY
    TBTSockAddr sockaddr;
    sockaddr.SetBTAddr( aDevAddr );
    sockaddr.SetPort( aPort );
    TRAPD(err, iHSServer->GetSocketAndTryToConnectL(sockaddr));
    if ( err != KErrNone )
        {
        TRACE_INFO( (_L("CHsServer::GetSocketAndTryToConnectL() error = %d"), err) )
        TRAP_IGNORE( HandleNewClientL(NULL, err));

        }

    TRACE_FUNC_EXIT
    }

void CHsCore::HandleSdpQueryError( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( (_L("aErr = %d"), aErr))
    if ( iObserver )
        {
        iObserver->HandleUnableToConnectClient();
        }
    TRACE_FUNC_EXIT
    }

void CHsCore::HandleServiceNotFound( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( (_L("aErr = %d"), aErr))
    if ( iObserver )
        {
        iObserver->HandleUnableToConnectClient();
        }
    TRACE_FUNC_EXIT
    }

void CHsCore::HandlePortNotFound( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( (_L("aErr = %d"), aErr))
    if ( iObserver )
        {
        iObserver->HandleUnableToConnectClient();
        }
    TRACE_FUNC_EXIT
    }

void CHsCore::HandleDesiredDeviceNotFound( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    TRACE_INFO( (_L("aErr = %d"), aErr))
    if ( iObserver )
        {
        iObserver->HandleUnableToConnectClient();
        }
    TRACE_FUNC_EXIT
    }

void CHsCore::HandleRemoteControllerConnected( TInt aErr )
    {
    TRACE_FUNC_ENTRY
    if ( iObserver && aErr == KErrNone )
        {
        iObserver->HandleConnectedToRemoteController();
        }
    TRACE_FUNC_EXIT
    }

void CHsCore::HandleRemoteControllerDisconnected( TInt /** aErr */)
    {
    TRACE_FUNC_ENTRY
    if ( iObserver )
        {
        iObserver->HandleDisconnectedFromRemoteController();
        }
    TRACE_FUNC_EXIT
    }