diff -r 000000000000 -r 4e1aa6a622a0 accessoryservices/accessoryserver/src/Server/AccSrvSubAsyComms.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/accessoryservices/accessoryserver/src/Server/AccSrvSubAsyComms.cpp Tue Feb 02 00:53:00 2010 +0200 @@ -0,0 +1,702 @@ +/* +* Copyright (c) 2002-2006 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: Subconnection class for session of ASYComms +* +*/ + + +// INCLUDE FILES +#include "AccSrvSubAsyComms.h" +#include "AccSrvMainSession.h" +#include "AccClientServerMessages.h" +#include "acc_debug.h" +#include "AccSrvServerModel.h" +#include "AccSrvASYProxyHandler.h" +#include + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS +//Main service implementation uid of BT-ASY stub for MT +const TUid KBTAsyMainServUidStub = {0x10200c7c}; +//Main service implementation uid of BT ASY +const TUid KBTAsyMainServUid = {0x1020897c}; + +// MACROS + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS + +// ============================= LOCAL FUNCTIONS =============================== + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::CAccSrvSubAsyComms +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CAccSrvSubAsyComms::CAccSrvSubAsyComms( + CASYProxyAPI* aProxy, + CAccSrvConnectionController* aConnectionController, + CAccSrvServerModel* aServerModel, + TUint aASYThreadID, + TUid aMainServiceUid ) + : CAccSrvSubBase( aProxy, aConnectionController,aServerModel ), + iOutstandingTrId( 0 ), + iTimeOutTrId ( 0 ), + iOutstandingProcessCmdId( ECmdBadFunction ), + iASYThreadID( aASYThreadID ), + iMainServiceUid( aMainServiceUid ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::CAccSrvSubAsyComms()" ); + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::CAccSrvSubAsyComms" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CAccSrvSubAsyComms::ConstructL() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::ConstructL()" ); + + iInitCommandTimer = CAccSrvProcessCommandTimer::NewL( this, KInitCmdTimeOut ); + iServerModel->AddASYThreadId( iASYThreadID ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::ConstructL - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CAccSrvSubAsyComms* CAccSrvSubAsyComms::NewL( + CASYProxyAPI* aProxy, + CAccSrvConnectionController* aConnectionController, + CAccSrvServerModel* aServerModel, + TUint aASYThreadID, + TUid aMainServiceUid ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::NewL()" ); + if ( !aProxy ) + { + User::Leave( KErrArgument ); + } + + CAccSrvSubAsyComms* self = new ( ELeave ) CAccSrvSubAsyComms( + aProxy, + aConnectionController, + aServerModel, + aASYThreadID, + aMainServiceUid ); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + COM_TRACE_1( "[AccFW:AccServer] CAccSrvSubAsyComms::NewL - return 0x%x", self ); + return self; + } + +// Destructor +CAccSrvSubAsyComms::~CAccSrvSubAsyComms() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::~CAccSrvSubAsyComms()" ); + + if ( iInitCommandTimer ) + { + delete iInitCommandTimer; + } + + if ( iProcessCommandTimer ) + { + delete iProcessCommandTimer; + } + + if( iObjectBuf ) + { + delete iObjectBuf; + } + + CancelNotifyProcessCommand( iMessage ); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::~CAccSrvSubAsyComms" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::DispatchMessageL +// Handles client request +// ----------------------------------------------------------------------------- +// +void CAccSrvSubAsyComms::DispatchMessageL( const RMessage2& aMessage ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::DispatchMessageL()" ); + + TInt function = aMessage.Function(); + + switch ( function ) + { + case EAccSrvNotifyProcessCommand: + { + NotifyProcessCommand( aMessage ); + break; + } + case EAccSrvCancelNotifyProcessCommand: + { + CancelNotifyProcessCommand( aMessage ); + break; + } + case EAccSrvProcessResponseTBool: + { + ProcessResponseL( aMessage, EProcessResponseTBool ); + break; + } + case EAccSrvProcessResponseTInt: + { + ProcessResponseL( aMessage, EProcessResponseTInt ); + break; + } + case EAccSrvProcessResponseTDes: + { + ProcessResponseL( aMessage, EProcessResponseTDes ); + break; + } + case EAccSrvProcessResponseObject: + { + ProcessResponseL( aMessage, EProcessResponseObject ); + break; + } + + case EAccSrvGetObjectBuffer: + { + TPtr8 ptrBuf( iObjectBuf->Ptr( 0 ) ); + aMessage.WriteL( KAccServParamPosFirst, ptrBuf ); + delete iObjectBuf; + iObjectBuf = NULL; + break; + } + default: + { + TRACE_ASSERT_ALWAYS; + COM_TRACE_1( "[AccFW:AccServer] CAccSrvSubAsyComms::DispatchMessageL - unhandled function %d", function ); + User::Leave( KErrNotSupported ); + break; + } + } // switch( function ) + + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::DispatchMessageL - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::NotifyProcessCommand +// Sets the NotifyProcessCommand to a handling queue +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAccSrvSubAsyComms::NotifyProcessCommand( const RMessage2& aMessage ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::NotifyProcessCommand()" ); + + // Add session to queue. + // Queue will call CAccSrvSubAsyComms::CompleteProcessCommandL() when client + // has sent request to ASY. + + // Exception: In initialization case asy-proxy-server makes + // the completition instead of client ( Loading complete ) + + iConnectionController->NotificationQueue().RegisterControlMessage( + ENotifyProcessCommand, + this ); + + // Copy client message for completion when client has sent request to ASY. + // Completion is done in CAccSrvSubAsyComms::CompleteProcessCommandL() + + // Exception: In initialization case asy-proxy-server makes + // the completition instead of client ( Loading complete ) + + iMessage = aMessage; + + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::NotifyProcessCommand - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::CancelNotifyProcessCommand +// ----------------------------------------------------------------------------- +// +void CAccSrvSubAsyComms::CancelNotifyProcessCommand( const RMessage2& /*aMessage*/ ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::CancelNotifyProcessCommand()" ); + + // Is command pending + if ( !iMessage.IsNull() ) + { + // Remove NotifyProcessCommand from queue. + iConnectionController->NotificationQueue().CancelControlMessage( + ENotifyProcessCommand, + this ); + iMessage.Complete( KErrCancel ); + } + + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::CancelNotifyProcessCommand - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::ProcessResponseL +// Handles responses of NotifyProcessCommand +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAccSrvSubAsyComms::ProcessResponseL( const RMessage2& aMessage, + TProcessResponseType aResponseType, + TBool aTimeOut ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::ProcessResponseL()" ); + + if ( iProcessCommandTimer ) + { + iProcessCommandTimer->Cancel(); + delete iProcessCommandTimer; + iProcessCommandTimer = NULL; + } + + TMsgID messageId( EUnknown ); + TPckgBuf tridPckgBuf; + TPckgBuf errPckgBuf; + TAccSrvValueTypeTBoolPckgBuf valueTBoolPckgBuf;// TBool + TPckgBuf valueTIntPckgBuf;// TInt + TASYBTAccInfo btInfo;// TDes + TPckg valueBTPckg( btInfo ); + TInt asyDataSize ( 0 ); + HBufC8 *asyData = NULL; + CBufFlat* objectBuf = NULL; + + // + // Allocated the buffer which is really needed! + // + if ( EProcessResponseTDes == aResponseType && + ECmdGetSupportedBTProfiles != iOutstandingProcessCmdId ) + { + asyDataSize = aMessage.GetDesLengthL( KAccServParamPosSecond ); + asyData = HBufC8::NewL( asyDataSize ); + CleanupStack::PushL( asyData ); + } + else if ( EProcessResponseObject == aResponseType ) + { + objectBuf = CBufFlat::NewL( KAccSrvObjectBaseStreamBufGranularity ); + CleanupStack::PushL( objectBuf ); + TInt bufLength( aMessage.GetDesLength( KAccServParamPosSecond ) ); + objectBuf->ResizeL( bufLength ); + } + else + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::ProcessResponseL() - Buffer is not needed!" ); + } + + if ( !aTimeOut ) + { + aMessage.ReadL( KAccServParamPosFirst, tridPckgBuf ); + if ( iOutstandingTrId != tridPckgBuf() ) + { + // There are no correcponding SetValueL()/GetValueL() pending + User::Leave( KErrNotFound ); + } + + switch ( aResponseType ) + { + case EProcessResponseTBool : + aMessage.ReadL( KAccServParamPosSecond, valueTBoolPckgBuf ); + aMessage.ReadL( KAccServParamPosThird, errPckgBuf ); + break; + case EProcessResponseTInt : + aMessage.ReadL( KAccServParamPosSecond, valueTIntPckgBuf ); + aMessage.ReadL( KAccServParamPosThird, errPckgBuf ); + break; + case EProcessResponseTDes : + if( ECmdGetSupportedBTProfiles == iOutstandingProcessCmdId ) + { + aMessage.ReadL( KAccServParamPosSecond, valueBTPckg ); + } + else + { + TPtr8 asyDataPtr = asyData->Des(); + aMessage.ReadL( KAccServParamPosSecond, asyDataPtr ); + } + aMessage.ReadL( KAccServParamPosThird, errPckgBuf ); + break; + case EProcessResponseObject : + { + // In set case do not read object buf ptr. + if( ECmdGetObjectValue == iOutstandingProcessCmdId ) + { + TPtr8 objectBufPtr( objectBuf->Ptr(0) ); + aMessage.ReadL( KAccServParamPosSecond, objectBufPtr ); + aMessage.ReadL( KAccServParamPosThird, errPckgBuf ); + } + else + { + aMessage.ReadL( KAccServParamPosThird, errPckgBuf ); + } + } + break; + + default: + { + TRACE_ASSERT_ALWAYS; + User::Leave( KErrGeneral ); + } + break; + } + } + else // Timed out + { + tridPckgBuf = iOutstandingTrId; + errPckgBuf = KErrTimedOut; + iTimeOutTrId = iOutstandingTrId; + } + + // This ASY command is handled so no more new requests can not be linked to this one + // ->Transaction filter can be removed + iConnectionController->ASYProxyHandler().RemoveTransactionID( iOutstandingTrId ); + + switch ( iOutstandingProcessCmdId ) + { + case ECmdSetValueBool: + case ECmdSetValueTInt: + case ECmdAccessoryUpdated: + case ECmdSetObjectValue: + { + messageId = ESetValue; + } + break; + case ECmdGetValueBool: + case ECmdGetValueTInt: + case ECmdGetValueTDes8: + case ECmdGetSupportedBTProfiles: + case ECmdGetObjectValue: + { + messageId = EGetValue; + } + break; + case ECmdProcessCommandInit: + { + if ( iInitCommandTimer->IsActive() ) + { + iInitCommandTimer->Cancel(); + CompleteProcessCommandInitL(); + } + } + break; + default: + { + TRACE_ASSERT_ALWAYS; + User::Leave( KErrGeneral ); + } + break; + } + + if ( iOutstandingProcessCmdId != ECmdProcessCommandInit ) + { + switch ( aResponseType ) + { + case EProcessResponseTBool : + iConnectionController->NotificationQueue().CompleteValueMessageL( + messageId, + valueTBoolPckgBuf(), + errPckgBuf(), + iOutstandingTrId ); + break; + case EProcessResponseTInt : + iConnectionController->NotificationQueue().CompleteValueMessageL( + messageId, + valueTIntPckgBuf(), + errPckgBuf(), + iOutstandingTrId ); + break; + case EProcessResponseTDes : + if( ECmdGetSupportedBTProfiles == iOutstandingProcessCmdId ) + { + iConnectionController->NotificationQueue().CompleteValueMessageL( + messageId, + valueBTPckg, + errPckgBuf(), + iOutstandingTrId ); + } + else + { + TPtr8 asyDataPtr = asyData->Des(); + iConnectionController->NotificationQueue().CompleteValueMessageL( + messageId, + asyDataPtr, + errPckgBuf(), + iOutstandingTrId ); + CleanupStack::PopAndDestroy( asyData ); + } + break; + case EProcessResponseObject : + { + TPtr8 objectBufPtr( objectBuf->Ptr(0) ); + iConnectionController->NotificationQueue().CompleteValueMessageL( + messageId, + iOutstandingTrId, + &objectBufPtr, + errPckgBuf() ); + CleanupStack::PopAndDestroy( objectBuf ); + } + break; + + default: + { + TRACE_ASSERT_ALWAYS; + User::Leave( KErrGeneral ); + } + break; + } + + } + + iOutstandingProcessCmdId = ECmdBadFunction; + iOutstandingTrId = 0; + + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::ProcessResponseL - return void" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::CompleteMessageL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CAccSrvSubAsyComms::CompleteMessageL( TMsgID /*aMsgID*/, + TInt /*aErrorCode*/, + TInt /*aUniqueID*/ ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::CompleteMessageL()" ); + + TRACE_ASSERT_ALWAYS; + + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::CompleteMessageL - return False" ); + + return EFalse; //message was not consumed + } +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::CompleteProcessCommandL +// Completes queued message +// Preconditions: +// 1. ECmdProcessCommandInit command is allways handled +// 2. Request must be meant for this subsession +// ----------------------------------------------------------------------------- +// +TBool CAccSrvSubAsyComms::CompleteProcessCommandL( + TProcessCmdId aCmdn, + TInt aTrId, + TASYCommandParamRecord& aASYCommandParamRecord, + TPtr8* aPtrBuf ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::CompleteProcessCommandL()" ); + + TBool messageConsumption( EFalse );// Return value tells should this subsession be removed from the queue + + if ( ECmdProcessCommandInit == aCmdn ) + { + messageConsumption = HandleCommandL( aCmdn, aTrId, aASYCommandParamRecord, aPtrBuf ); + } + else + { + if ( iServerModel->IsMyRequest( + iASYThreadID, aASYCommandParamRecord.iGenericID.UniqueID() ) ) + { + messageConsumption = HandleCommandL( aCmdn, aTrId, aASYCommandParamRecord, aPtrBuf ); + } + else + { + //Not for us + //Special handling for BT-ASY + if ( ( KBTAsyMainServUidStub.iUid == iMainServiceUid.iUid ) || + ( KBTAsyMainServUid.iUid == iMainServiceUid.iUid ) ) + { + if ( aASYCommandParamRecord.iGenericID.PhysicalConnectionCaps( KPCBluetooth ) )//BT + { + messageConsumption = HandleCommandL( aCmdn, aTrId, aASYCommandParamRecord, aPtrBuf ); + } + } + else + { + //This subsession is not serving BT-ASY + } + } + } + + COM_TRACE_1( "[AccFW:AccServer] CAccSrvSubAsyComms::CompleteProcessCommandL - return %d", messageConsumption ); + return messageConsumption; + } + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::HandleCommandL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +TBool CAccSrvSubAsyComms::HandleCommandL( TProcessCmdId aCmdn, + TInt aTrId, + TASYCommandParamRecord& aASYCommandParamRecord, + TPtr8* aPtrBuf ) + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::HandleCommandL()" ); + TInt err( KErrNone ); + + iOutstandingProcessCmdId = aCmdn; + iOutstandingTrId = aTrId; + + TProxyCommandPckgBuf params; + params().iCmdId = aCmdn; + params().iTrId = aTrId; + params().iTimeOutTrId = iTimeOutTrId; + params().iAsyCmdParams = aASYCommandParamRecord; + iMessage.WriteL( KAccServParamPosFirst, params ); + + + if( ECmdProcessCommandInit != aCmdn ) + { + err = HandleObjectBufferWriteL( aPtrBuf ); + iProcessCommandTimer = CAccSrvProcessCommandTimer::NewL( this ); + iProcessCommandTimer->StartTimer(); + } + else + { + iInitCommandTimer->StartTimer(); + } + + iMessage.Complete( err ); + + iTimeOutTrId = 0; + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::HandleCommandL - return ETrue" ); + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::HandleObjectBufferWriteL() +// ----------------------------------------------------------------------------- +TInt CAccSrvSubAsyComms::HandleObjectBufferWriteL( TPtr8* aPtrBuf ) + { + COM_TRACE_1( "[AccFW:AccServer] CAccSrvSubAsyComms::HandleObjectBufferWriteL(0x%x)", aPtrBuf ); + TInt err( KErrNone ); + + if( !aPtrBuf ) + { + // There are no buffer to handle + COM_TRACE_1( "[AccFW:AccServer] CAccSrvSubAsyComms::HandleObjectBufferWriteL - no buffer, return %d", err ); + return err; + } + + TInt size=iMessage.GetDesMaxLength( KAccServParamPosSecond ); + + if( aPtrBuf->Size() <= size ) + { + iMessage.WriteL( KAccServParamPosSecond, *aPtrBuf ); + } + else + { + //Return a new buffer size to client + err = KErrOverflow; + CBufFlat* buf = CBufFlat::NewL( sizeof( KMaxTUint ) ); + CleanupStack::PushL( buf ); + buf->ResizeL( sizeof(KMaxTUint) ); + + RBufWriteStream wStrm; + (void) wStrm.Open( *buf ); + CleanupClosePushL( wStrm ); + wStrm.WriteInt32L( aPtrBuf->Size() );//new buffer size + wStrm.CommitL(); + CleanupStack::PopAndDestroy( &wStrm ); + + TPtr8 ptr( buf->Ptr( 0 ) ); + iMessage.WriteL( KAccServParamPosSecond, ptr ); + CleanupStack::PopAndDestroy( buf ); + + //Store current buffer for later retrival + iObjectBuf = CBufFlat::NewL( KAccSrvObjectBaseStreamBufGranularity ); + iObjectBuf->ResizeL( aPtrBuf->Size() ); + iObjectBuf->Write( 0, *aPtrBuf ); + + } + + + COM_TRACE_1( "[AccFW:AccServer] CAccSrvSubAsyComms::HandleObjectBufferWriteL - return %d", err ); + return err; + } + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::CompleteProcessCommandInitL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +void CAccSrvSubAsyComms::CompleteProcessCommandInitL() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::CompleteProcessCommandInitL()" ); + + // Note, Must NOT leave before next call + iServerModel->SetASYsLoadCompleted(); + + iConnectionController->InitializeConnectionStatusL(); + + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::CompleteProcessCommandInitL" ); + } + +// ----------------------------------------------------------------------------- +// CAccSrvSubAsyComms::ProcessCommandTimeOutCompleteL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +void CAccSrvSubAsyComms::ProcessCommandTimeOutCompleteL() + { + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::ProcessCommandTimeOutCompleteL()" ); + + switch( iOutstandingProcessCmdId ) + { + case ECmdSetValueBool: + case ECmdGetValueBool: + ProcessResponseL( iMessage, EProcessResponseTBool, ETrue ); + break; + case ECmdSetValueTInt: + case ECmdGetValueTInt: + ProcessResponseL( iMessage, EProcessResponseTInt, ETrue ); + break; + case ECmdGetValueTDes8: + case ECmdGetSupportedBTProfiles: + ProcessResponseL( iMessage, EProcessResponseTDes, ETrue ); + break; + case ECmdSetObjectValue: + case ECmdGetObjectValue: + ProcessResponseL( iMessage, EProcessResponseObject, ETrue ); + break; + default: + break; + } + + COM_TRACE_( "[AccFW:AccServer] CAccSrvSubAsyComms::ProcessCommandTimeOutCompleteL" ); + } + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + +// End of File