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