/*
* 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
}