hti/HtiCommPlugins/HtiBtCommPlugin/BtEngine/src/BtSerialClient.cpp
changeset 0 a03f92240627
child 4 73ff0d268e1d
--- /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