--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hti/HtiCommPlugins/HtiBtCommPlugin/BtEngine/src/BtSerialClient.cpp Tue Feb 02 01:57:15 2010 +0200
@@ -0,0 +1,443 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Bluetooth serial client.
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <c32comm.h>
+#include "BtSerialClient.h"
+#include "MessageServiceSearcher.h"
+#include "BtSerialEngine.pan"
+#include "HtiBtEngineLogging.h"
+#include "socketswriter.h"
+#include "socketsreader.h"
+
+// CONSTANTS
+const TUint KServiceUid = 0x12341101;
+
+// ----------------------------------------------------------------------------
+EXPORT_C CBtSerialClient* CBtSerialClient::NewL( MBtSerialClientObserver& aObserver )
+ {
+ CBtSerialClient* self = new ( ELeave ) CBtSerialClient( aObserver );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+CBtSerialClient::CBtSerialClient( MBtSerialClientObserver& aObserver )
+: CActive( CActive::EPriorityStandard ), iObserver( aObserver ),
+ iState( EWaitingToGetDevice ), iCurrentServiceIndex( 0 )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C CBtSerialClient::~CBtSerialClient()
+ {
+ delete iSocketReader;
+ delete iSocketWriter;
+
+ Cancel();
+
+ iSocket.Close();
+ iSocketServer.Close();
+
+ delete iServiceSearcher;
+
+ iPowerControl.Close();
+ }
+
+// ----------------------------------------------------------------------------
+void CBtSerialClient::ConstructL()
+ {
+ LOG_D( "CBtSerialClient::ConstructL()" );
+
+ TInt err = iPowerControl.Open();
+ if ( err != KErrNone )
+ {
+ LOGFMT_E( "Could not open BT power controller %d", err );
+ User::Leave( err );
+ }
+
+ // Check current BT power state and try to turn ON if necessary
+ TBTPowerState powerState = EBTOff;
+ err = iPowerControl.GetPower( ( TBTPowerState& ) powerState, NULL );
+ LOGFMT_D( "GetPower return code %d", err );
+ LOGFMT_D( "Current BT power state %d", powerState );
+ if ( powerState != EBTOn )
+ {
+ LOG_I( "Turning BT ON" );
+ TRequestStatus status = KRequestPending;
+ iPowerControl.SetPower( EBTOn, NULL, status );
+ User::WaitForRequest( status );
+ LOGFMT_D( "SetPower return code %d", status.Int() );
+ if ( status != KErrNone && status != KErrAlreadyExists )
+ {
+ LOGFMT_E( "Could not turn BT on, err: %d", status.Int() );
+ User::Leave( status.Int() );
+ }
+ LOG_I( "Waiting a while for BT to turn on" );
+ User::After( 1 * 1000 * 1000 );
+ }
+
+ err = StartC32();
+ LOGFMT_D( "StartC32 return code %d", err );
+
+ LOG_I( "Continuing BT connect" );
+
+ iServiceSearcher = CMessageServiceSearcher::NewL();
+ User::LeaveIfError( iSocketServer.Connect() );
+ iSocketReader = CSocketsReader::NewL( *this, iSocket );
+ iSocketWriter = CSocketsWriter::NewL( *this, iSocket );
+ }
+
+// ----------------------------------------------------------------------------
+void CBtSerialClient::DoCancel()
+ {
+ LOG_W("CBtSerialClient::DoCancel(): Doing nothing");
+ }
+
+// ----------------------------------------------------------------------------
+void CBtSerialClient::RunL()
+ {
+ if ( iStatus != KErrNone )
+ {
+ switch ( iState )
+ {
+ case EGettingDevice:
+ if ( iStatus == KErrCancel )
+ {
+ LOG_W( "CBtSerialClient: No device selected" );
+ }
+ iState = EWaitingToGetDevice;
+ iObserver.ConnectedToServer( iStatus.Int() );
+ break;
+ case EGettingService:
+ LOGFMT_W( "CBtSerialClient: Failed to fetch remote service: %d", iStatus.Int() );
+ iObserver.ConnectedToServer( iStatus.Int() );
+ iState = EWaitingToGetDevice;
+ break;
+ case EGettingConnection:
+ LOGFMT_W( "CBtSerialClient: Failed to connect to remote service: %d", iStatus.Int() );
+ if ( iCurrentServiceIndex < iServiceSearcher->ServiceCount() )
+ {
+ // Try another service
+ iCurrentServiceIndex++;
+ ConnectToServerL(); // establish RFComm connection
+ }
+ else
+ {
+ iState = EWaitingToGetDevice;
+ iObserver.ConnectedToServer( iStatus.Int() );
+ }
+ break;
+ case EConnected:
+ LOGFMT_I( "CBtSerialClient: Lost connection: %d", iStatus.Int() )
+ DisconnectFromServer();
+ iState = EDisconnecting;
+ break;
+ case EDisconnecting:
+ LOGFMT_I("CBtSerialClient: Disconnected from server: %d", iStatus.Int() );
+ iSocket.Close();
+ iState = EWaitingToGetDevice;
+ iObserver.DisconnectedFromServer();
+ break;
+ default:
+ Panic( EBTPointToPointInvalidLogicState );
+ break;
+ }
+ }
+ else // iStatus = KErrNone
+ {
+ switch ( iState )
+ {
+ case EGettingDevice:
+ // found a device now search for a suitable service
+ LOGFMT_I("CBtSerialClient: Found device: %S. Finding correct service.", &(iServiceSearcher->ResponseParams().DeviceName()) );
+ iState = EGettingService;
+ iStatus = KRequestPending; // this means that the RunL can not
+ // be called until this program
+ // does something to iStatus
+ iBTServerDevice = iServiceSearcher->BTDevAddr();
+ iServiceSearcher->FindServiceL( iBTServerDevice, iStatus );
+ SetActive();
+ break;
+ case EGettingService:
+ LOGFMT_I("CBtSerialClient: Found %d remote services", iServiceSearcher->ServiceCount());
+ iState = EGettingConnection;
+ ConnectToServerL(); // establish RFComm connection
+ break;
+ case EGettingConnection:
+ LOG_I( "CBtSerialClient: Connected to remote service" );
+ iState = EConnected;
+ iObserver.ConnectedToServer( KErrNone );
+ break;
+ case EDisconnecting:
+ LOG_I( "CBtSerialClient: Disconnecting" );
+ iSocket.Close();
+ iState = EWaitingToGetDevice;
+ iObserver.DisconnectedFromServer();
+ break;
+ default:
+ LOGFMT_E( "CBtSerialClient: Invalid logic state in RunL: %d. Will panic", iState );
+ Panic( EBTPointToPointInvalidLogicState );
+ break;
+ };
+ }
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C void CBtSerialClient::ConnectL()
+ {
+ if ( iState == EWaitingToGetDevice && !IsActive() )
+ {
+ LOG_D( "CBtSerialClient: Connecting by user selection" );
+ iState = EGettingDevice;
+ iServiceSearcher->SelectDeviceByDiscoveryL( iStatus );
+ SetActive();
+ }
+ else
+ {
+ LOG_W( "CBtSerialClient: Already connecting or connected" );
+ User::Leave( KErrInUse );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C void CBtSerialClient::ConnectL( const TBTDevAddr aBTServerDevice,
+ const TInt aPort )
+ {
+ if ( iState == EWaitingToGetDevice && !IsActive() )
+ {
+ if ( aPort >= 0 )
+ {
+ // If there was a valid port given, add it as the first port to try
+ iServiceSearcher->AppendPort( aPort );
+ }
+ LOG_D( "CBtSerialClient: Connecting by address" );
+ iBTServerDevice = aBTServerDevice;
+ iServiceSearcher->FindServiceL( iBTServerDevice, iStatus );
+ iState = EGettingService;
+ iStatus = KRequestPending; // this means that the RunL can not
+ // be called until this program
+ // does something to iStatus
+ SetActive();
+ }
+ else
+ {
+ LOG_W("CBtSerialClient: Already connecting or connected");
+ User::Leave( KErrInUse );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C void CBtSerialClient::ConnectL( const TDesC& aBTServerDeviceName,
+ const TInt aPort )
+ {
+ if ( iState == EWaitingToGetDevice && !IsActive() )
+ {
+ if ( aPort >= 0 )
+ {
+ // If there was a valid port given, add it as the first port to try
+ iServiceSearcher->AppendPort( aPort );
+ }
+ LOG_D( "CBtSerialClient: Connecting by name" );
+ iState = EGettingDevice;
+ iServiceSearcher->SelectDeviceByNameL( aBTServerDeviceName, iStatus );
+ SetActive();
+ }
+ else
+ {
+ LOG_W( "CBtSerialClient: Already connecting or connected" );
+ User::Leave( KErrInUse );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C TBTDevAddr CBtSerialClient::ServerAddressL()
+ {
+ if ( !Connected() )
+ {
+ LOG_E( "CBtSerialClient: ServerAddressL: Not connected" );
+ User::Leave( KErrNotReady );
+ }
+ return iBTServerDevice;
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C void CBtSerialClient::Disconnect()
+ {
+ if ( iState == EConnected )
+ {
+ DisconnectFromServer();
+ iState = EDisconnecting;
+ }
+ else
+ {
+ LOG_W( "CBtSerialClient: Disconnect: Not connected" );
+ User::Leave( KErrDisconnected );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+void CBtSerialClient::DisconnectFromServer()
+ {
+ // Terminate all operations
+ iSocket.CancelAll();
+ Cancel();
+ iSocketReader->Cancel();
+ iSocketWriter->CancelSending();
+
+ LOG_I( "CBtSerialClient: Disconnecting from server" );
+ iSocket.Shutdown( RSocket::ENormal, iStatus );
+ SetActive();
+ }
+
+// ----------------------------------------------------------------------------
+void CBtSerialClient::ConnectToServerL()
+ {
+ LOG_I("CBtSerialClient: ConnectToServerL")
+ User::LeaveIfError( iSocket.Open( iSocketServer, KStrRFCOMM ) );
+
+ TBTSockAddr address;
+ address.SetBTAddr( iServiceSearcher->BTDevAddr() );
+ address.SetPort( iServiceSearcher->Port( iCurrentServiceIndex ) );
+ TBTServiceSecurity btSec;
+ btSec.SetUid( TUid::Uid( KServiceUid ) );
+ btSec.SetAuthentication( EMitmNotRequired );
+ btSec.SetEncryption( EFalse );
+ btSec.SetAuthorisation( EFalse );
+ btSec.SetDenied( EFalse );
+ address.SetSecurity( btSec );
+
+ LOGFMT_I("CBtSerialClient: ConnectToServerL: Port = %d", address.Port() );
+ iSocket.Connect( address, iStatus );
+
+#ifdef __WINS__
+ User::After( 1 ); // Needed to allow emulator client to connect to server
+#endif
+
+ SetActive();
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C void CBtSerialClient::SendL(const TDesC8& aData)
+ {
+ if ( !Connected() )
+ {
+ LOG_E( "CBtSerialClient: SendL: Not connected" );
+ User::Leave( KErrNotReady );
+ }
+
+ LOGFMT_D("CBtSerialClient::SendL: Sending data (max first 32 bytes): \"%S\"", &(aData.Left(32)));
+ iSocketWriter->SendL( aData ); // Add to data queue and start sending
+ LOG_D("CBtSerialClient::SendL: Sent to socket");
+ }
+
+EXPORT_C void CBtSerialClient::ReadAsyncL()
+ {
+ if ( !Connected() )
+ {
+ LOG_E( "CBtSerialClient: ReadAsyncL: Not connected" );
+ User::Leave( KErrNotReady );
+ }
+ iSocketReader->ReadAsync();
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C TInt CBtSerialClient::FreeSpaceInSendBuffer()
+ {
+ return iSocketWriter->FreeSpaceInSendBuffer();
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C TInt CBtSerialClient::SendBufferMaxSize()
+ {
+ return iSocketWriter->SendBufferMaxSize();
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C TBool CBtSerialClient::Connected()
+ {
+ return (iState == EConnected);
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C TBool CBtSerialClient::Connecting()
+ {
+ return ( ( iState == EGettingDevice ) ||
+ ( iState == EGettingService ) ||
+ ( iState == EGettingConnection ) );
+ }
+
+// ----------------------------------------------------------------------------
+EXPORT_C TInt CBtSerialClient::ServicePort()
+ {
+ if ( !Connected() )
+ {
+ return KErrDisconnected;
+ }
+ return iServiceSearcher->Port( iCurrentServiceIndex );
+ }
+
+// ----------------------------------------------------------------------------
+void CBtSerialClient::ReportError( TErrorType aErrorType, TInt aErrorCode )
+ {
+ LOGFMT_W( "CBtSerialClient::ReportError: %d", aErrorCode );
+ // From socket reader or writer
+ switch ( aErrorType )
+ {
+ case EDisconnected:
+ {
+ LOG_I( "CBtSerialClient: disconnected" );
+ }
+ break;
+ case ETimeOutOnWrite:
+ {
+ LOG_I( "CBtSerialClient: timout writing data. Disconnecting from server" );
+ }
+ break;
+ case EGeneralReadError:
+ {
+ LOG_I( "CBtSerialClient: general read error. Disconnecting from server" );
+ }
+ break;
+ case EGeneralWriteError:
+ {
+ LOG_I( "CBtSerialClient: general write error. Disconnecting from server" );
+ }
+ break;
+ }
+ Disconnect();
+ aErrorCode = aErrorCode;
+ }
+
+// ----------------------------------------------------------------------------
+ void CBtSerialClient::NewData( const TDesC8& aData )
+ {
+ iObserver.DataFromServer( aData );
+ }
+
+// ----------------------------------------------------------------------------
+void CBtSerialClient::AllBufferedDataSent()
+ {
+ iObserver.AllBufferedDataSent();
+ }
+
+// End of File