diff -r 7fdc9a71d314 -r 8ad140f3dd41 hti/HtiCommPlugins/HtiBtCommPlugin/BtEngine/src/BtSerialClient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hti/HtiCommPlugins/HtiBtCommPlugin/BtEngine/src/BtSerialClient.cpp Wed Oct 13 16:17:58 2010 +0300 @@ -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 +#include +#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