diff -r 000000000000 -r 4e1aa6a622a0 hwrmhaptics/hapticspluginmanager/src/hwrmhapticspluginmanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hwrmhaptics/hapticspluginmanager/src/hwrmhapticspluginmanager.cpp Tue Feb 02 00:53:00 2010 +0200 @@ -0,0 +1,583 @@ +/* +* Copyright (c) 2008 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: Haptics server plugin handler implementation. +* +*/ + + +#include +#include +#include +#include + +#include "hwrmhapticspluginmanager.h" +#include "hwrmhapticsclientserver.h" +#include "hwrmhapticsservice.h" +#include "hwrmhapticstrace.h" +#include "hwrmhapticstransactiondata.h" +#include "hwrmhapticsinternalcrkeys.h" +#include "hwrmhapticsuid.h" + +_LIT( KPanicCategory, "HWRMHapticsPluginManager" ); + +// HWRMHaptics uid file +_LIT( KHapticsUidFilename, "hwrmhapticsuid.ini" ); + +// --------------------------------------------------------------------------- +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +EXPORT_C CHWRMHapticsPluginManager* CHWRMHapticsPluginManager::NewL( + CHWRMHapticsCommonData& aHapticsCommonData, + TInt aRequestTimeout ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::NewL()" ) ) ); + + CHWRMHapticsPluginManager* self = + new ( ELeave ) CHWRMHapticsPluginManager( aHapticsCommonData, + aRequestTimeout ); + CleanupStack::PushL( self ); + + self->ConstructL(); + + CleanupStack::Pop( self ); + + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::NewL - return 0x%x" ), self ) ); + + return self; + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CHWRMHapticsPluginManager::~CHWRMHapticsPluginManager() + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::~CHWRMHapticsPluginManager()" ) ) ); + + if ( iPlugin ) + { + // Cancel any ongoing requests + while ( iTransactionList->FirstItem() ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::~CHWRMHapticsPluginManager - Canceling transaction %d" ), iTransactionList->FirstItem()->TransactionId() ) ); + TRAPD( err, CancelCommandL( + iTransactionList->FirstItem()->TransactionId() ) ); + + if ( err != KErrNone ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::~CHWRMHapticsPluginManager - Canceling transaction %d failed" ), iTransactionList->FirstItem()->TransactionId() ) ); + } + } + + delete iPlugin; + iPlugin = NULL; + } + + delete iPluginTimer; + // delete transaction list + delete iTransactionList; + + delete iHapticsUid; + + delete iRepository; + + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::~CHWRMHapticsPluginManager - return " )) ); + } + +// --------------------------------------------------------------------------- +// Handles plugin requests from sessions. Only one concurrent request +// is supported. +// --------------------------------------------------------------------------- +// +TUint8 CHWRMHapticsPluginManager::ProcessCommandL( + TInt aCommandId, + TDesC8& aData, + CHWRMHapticsService* aCompletionCallback ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::ProcessCommandL(0x%x, , 0x%x)" ), aCommandId, aCompletionCallback ) ); + + if ( !iPlugin ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::ProcessCommandL - No actuator!" ) ) ); + User::Leave( KErrBadHandle ); + } + + // Generate new transaction ID. + iTransIdCounter++; + if ( iTransIdCounter == 0 ) + { + // Counter will overflow back to zero when it hits max. + // However, zero indicates completed transaction as return value, so + // increase counter again. + iTransIdCounter++; + } + + // If we run out of transIds, return server is busy. + if ( iTransactionList->FindTransaction( iTransIdCounter, EFalse ) ) + { + User::Leave( KErrServerBusy ); + } + + // Create transaction data before call in case it leaves + TTime obsoletionTime; + obsoletionTime.UniversalTime(); + obsoletionTime += iRequestTimeout; + CHWRMHapticsTransactionData* data = + new (ELeave) CHWRMHapticsTransactionData( aCompletionCallback, + iTransIdCounter, + aCommandId, + obsoletionTime ); + + // Push transaction data to cleanup stack so that it will clean + // out if ProcessCommandL leaves. + CleanupStack::PushL( data ); + + iPlugin->ProcessCommandL( aCommandId, data->TransactionId(), aData ); + + TUint8 retval( 0 ); + + // data still needed, do not destroy, just pop + CleanupStack::Pop( data ); + + // Add data to list + iTransactionList->AddTransaction( data ); + + retval = data->TransactionId(); + + // Start timer if it is not already started + if ( !iPluginTimer->IsActive() ) + { + iPluginTimer->Set( iRequestTimeout ); + } + + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::ProcessCommandL - return 0x%x" ), retval ) ); + + return retval; + + } + +// --------------------------------------------------------------------------- +// Cancels the currently executing request +// --------------------------------------------------------------------------- +// +void CHWRMHapticsPluginManager::CancelCommandL( TUint8 aTransId ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::CancelCommandL()" )) ); + + if ( !iPlugin ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::CancelCommandL - No actuator!" ) ) ); + User::Leave( KErrBadHandle ); + } + + // Find correct transaction data and remove it from list + CHWRMHapticsTransactionData* data = + static_cast( + iTransactionList->FindTransaction( aTransId, ETrue ) ); + + // cancel request timer if no more transactions open + if ( iTransactionList->Count() == 0 ) + { + iPluginTimer->Cancel(); + } + + // If transaction is not open, do nothing + // Do not cancel if request has no callback (i.e. final destructor + // state restorings) + // (these are canceled by timeout if they do not complete successfully) + if ( data && data->CompletionCallback() ) + { + CleanupStack::PushL( data ); + + iPlugin->CancelCommandL( data->TransactionId(), data->CommandId() ); + + // Destroy the transaction data, since transaction is over. + CleanupStack::PopAndDestroy( data ); + } + else + { + if ( data ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::CancelCommandL - Not canceled because no callback" ) ) ); + + // Push data back to list + iTransactionList->AddTransaction( data ); + } + else + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::CancelCommandL - Not canceled because no transaction found" ) ) ); + } + } + + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::CancelCommandL - return" ) ) ); + } + +// --------------------------------------------------------------------------- +// Called by the plugin to inform its state. Sends notification of the state +// to all listening clients. +// --------------------------------------------------------------------------- +// +void CHWRMHapticsPluginManager::PluginEnabled( + THWRMLogicalActuators aActuator, + TBool aEnabled ) + { + MHWRMHapticsActuatorObserver::THWRMActuatorEvents event = + MHWRMHapticsActuatorObserver::EHWRMActuatorDisabled; + + if ( aEnabled ) + { + event = MHWRMHapticsActuatorObserver::EHWRMActuatorEnabled; + } + + iHapticsCommonData.BroadcastActuatorEvent( event, aActuator ); + } + +// --------------------------------------------------------------------------- +// Routes response from plugin to correct service instance +// --------------------------------------------------------------------------- +// +void CHWRMHapticsPluginManager::ProcessResponseL( TInt aCommandId, + TUint8 aTransId, + const TDesC8& aData ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::ProcessResponseL(0x%x, 0x%x, )" ), aCommandId, aTransId ) ); + + // Find and remove correct transaction data and remove it from queue + CHWRMHapticsTransactionData* data = + static_cast( + iTransactionList->FindTransaction( aTransId, ETrue ) ); + + // cancel request timer if no more transactions open + if ( iTransactionList->Count() == 0 ) + { + iPluginTimer->Cancel(); + } + + // If transaction is not open, response not expected. + if ( data ) + { + CleanupStack::PushL( data ); + + // Check that command ID is the expected one + if ( data->CommandId() != aCommandId ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::ProcessResponseL - Command ID mismatch, expected: 0x%x, got 0x%x" ), data->CommandId(), aCommandId ) ); + User::Leave( KErrBadHandle ); + } + + // Route data to callback service if one is needed + if ( data->CompletionCallback() ) + { + data->CompletionCallback()->ProcessResponseL( aCommandId, + aTransId, + aData ); + } + + CleanupStack::PopAndDestroy( data ); + data = NULL; + } + else + { + // There is problem in adaptation, as unexpected transaction was completed. + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::ProcessResponseL - No transaction data found!" ) ) ); + User::Leave( KErrBadHandle ); + } + + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::ProcessResponseL - return" ) ) ); + } + +// --------------------------------------------------------------------------- +// Cancels all obsolete transactions. TimerId is irrelevant as only one timer. +// --------------------------------------------------------------------------- +// +void CHWRMHapticsPluginManager::GenericTimerFired( TInt /*aTimerId*/, + TBool /*aCutOff*/ ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::GenericTimerFired()" ) ) ); + + __ASSERT_ALWAYS( iPlugin, User::Panic( KPanicCategory, + EPanicBadHandle ) ); + + // Since requests are added to end of list always, they are in order + // of obsolescense. + // Cancel requests that are obsolete and notify callback service + TInt err( KErrNone ); + TTime now; + now.UniversalTime(); + + CHWRMHapticsTransactionData* data = + static_cast( + iTransactionList->FirstItem() ); + + while ( data && ( data->TransactionObsoletionTime() < now ) ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::GenericTimerFired - Canceling obsolete transaction 0x%x" ), data->TransactionId() ) ); + + // Cancel transaction. + TUint8 trId( data->TransactionId() ); + TRAP(err, iPlugin->CancelCommandL( trId, data->CommandId() ) ); + + if ( err != KErrNone ) + { + // Ignore errors as we cannot do anything about it + // anyway. Just trace. + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::GenericTimerFired - Canceling obsolete transaction FAILED (%d)!" ), err ) ); + } + + if ( data->CompletionCallback() ) + { + data->CompletionCallback()->CancelRequest( trId ); + } + + // Destroy the transaction data, since transaction is over. + iTransactionList->RemoveFirstItem(); + delete data; + + // get next data to check + data = static_cast( + iTransactionList->FirstItem() ); + } + + // Restart timer if there is more transactions in list + if ( data ) + { + iPluginTimer->Set( iRequestTimeout ); + } + + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::GenericTimerFired - return" ) ) ); + } + +// --------------------------------------------------------------------------- +// It retrieves the supported actuator information from plugins. +// --------------------------------------------------------------------------- +// +TUint32 CHWRMHapticsPluginManager::GetSupportedActuatorInfo() + { + return iSupActuators; + } + +// --------------------------------------------------------------------------- +// Opens the plugin appropriate for the actuator to be opened. +// --------------------------------------------------------------------------- +// +TBool CHWRMHapticsPluginManager::OpenPluginToActuatorL( + THWRMLogicalActuators aActuator ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::OpenPluginToActuator - Actuator = %d " ), aActuator) ); + + TBool created = EFalse; + + // check if actuator type is supported + if ( !( aActuator & iSupActuators ) ) + { + // not supported + User::Leave( KErrNotSupported ); + } + + if ( !iPlugin ) + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::OpenPluginToActuator - Creating plugin instance." ) ) ); + + // map actuator type to type cenrep id + TInt adaptationCenrepId(0); + switch( aActuator ) + { + case EHWRMLogicalActuatorAny: + { + adaptationCenrepId = KHWRMHapticsPluginAnyAdaptation; + break; + } + case EHWRMLogicalActuatorDevice: + { + adaptationCenrepId = KHWRMHapticsPluginDeviceAdaptation; + break; + } + case EHWRMLogicalActuatorPrimaryDisplay: + { + adaptationCenrepId = KHWRMHapticsPluginPrimaryDisplayAdaptation; + break; + } + case EHWRMLogicalActuatorSecondaryDisplay: + { + adaptationCenrepId = KHWRMHapticsPluginSecondaryDisplayAdaptation; + break; + } + case EHWRMLogicalActuatorGame: + { + adaptationCenrepId = KHWRMHapticsPluginGameAdaptation; + break; + } + case EHWRMLogicalActuatorGameLeft: + { + adaptationCenrepId = KHWRMHapticsPluginGameLeftAdaptation; + break; + } + case EHWRMLogicalActuatorGameRight: + { + adaptationCenrepId = KHWRMHapticsPluginGameRightAdaptation; + break; + } + case EHWRMLogicalActuatorExternalVibra: + { + adaptationCenrepId = KHWRMHapticsPluginExternalVibraAdaptation; + break; + } + default: + adaptationCenrepId = KHWRMHapticsPluginAnyAdaptation; + break; + } + + TInt adaptationPluginUid( 0 ); + User::LeaveIfError( iRepository->Get( adaptationCenrepId, + adaptationPluginUid ) ); + + // create plugin instance with the given uid + TRAPD( err, iPlugin = CHWRMHapticsPluginService::NewL( + TUid::Uid( adaptationPluginUid ), this ) ); + + // if the plugin with given uid was not found, the + // actuator type is not supported + if ( err == KErrNotFound ) + { + err = KErrNotSupported; + } + + User::LeaveIfError( err ); + + created = ETrue; + } + + return created; + } + +// --------------------------------------------------------------------------- +// Checks if automatic license setting is allowed. The actual check is done +// in CHWRMHapticsUid helper class. +// --------------------------------------------------------------------------- +// +TBool CHWRMHapticsPluginManager::LicenseAutoSettingAllowed( + const RMessage2& aMessage ) + { + return iHapticsUid->LicenseAutoSetAllowed( aMessage ); + } + +// --------------------------------------------------------------------------- +// C++ constructor +// --------------------------------------------------------------------------- +// +CHWRMHapticsPluginManager::CHWRMHapticsPluginManager( + CHWRMHapticsCommonData& aHapticsCommonData, + TInt aRequestTimeout ) + : iHapticsCommonData( aHapticsCommonData ), + iTransIdCounter( 0 ), + iRequestTimeout( aRequestTimeout ) + { + } + +// --------------------------------------------------------------------------- +// 2nd phase constructor. +// --------------------------------------------------------------------------- +// +void CHWRMHapticsPluginManager::ConstructL() + { + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::ConstructL()" )) ); + + // create transaction list and timer + iTransactionList = new( ELeave ) CHWRMHapticsPluginTransactionList(); + iPluginTimer = CHWRMHapticsGenericTimer::NewL( this, iRequestTimeout, 0 ); + + iRepository = CRepository::NewL( KCRUidHWRMHapticsPlugins ); + + // get all supported actuator information + iSupActuators = FindSupportedActuatorInfoL(); + + // create UID file parser + iHapticsUid = CHWRMHapticsUid::NewL( KHapticsUidFilename ); + + COMPONENT_TRACE( ( _L( "CHWRMHapticsPluginManager::ConstructL - return" )) ); + } + +// --------------------------------------------------------------------------- +// Finds the supported actuator information from plugins. +// --------------------------------------------------------------------------- +// +TUint32 CHWRMHapticsPluginManager::FindSupportedActuatorInfoL() + { + TUint32 supportedActuators( 0 ); + + // Any + AddInfoIfSupportedL( KHWRMHapticsPluginAnyAdaptation, + EHWRMLogicalActuatorAny, + supportedActuators ); + + // Device + AddInfoIfSupportedL( KHWRMHapticsPluginDeviceAdaptation, + EHWRMLogicalActuatorDevice, + supportedActuators ); + + // Primary Display + AddInfoIfSupportedL( KHWRMHapticsPluginPrimaryDisplayAdaptation, + EHWRMLogicalActuatorPrimaryDisplay, + supportedActuators ); + + // Secondary Display + AddInfoIfSupportedL( KHWRMHapticsPluginSecondaryDisplayAdaptation, + EHWRMLogicalActuatorSecondaryDisplay, + supportedActuators ); + + // Game + AddInfoIfSupportedL( KHWRMHapticsPluginGameAdaptation, + EHWRMLogicalActuatorGame, + supportedActuators ); + + // Game Left + AddInfoIfSupportedL( KHWRMHapticsPluginGameLeftAdaptation, + EHWRMLogicalActuatorGameLeft, + supportedActuators ); + + // Game Right + AddInfoIfSupportedL( KHWRMHapticsPluginGameRightAdaptation, + EHWRMLogicalActuatorGameRight, + supportedActuators ); + + // External Vibra + AddInfoIfSupportedL( KHWRMHapticsPluginExternalVibraAdaptation, + EHWRMLogicalActuatorExternalVibra, + supportedActuators ); + + return supportedActuators; + } + +// --------------------------------------------------------------------------- +// If given actuator type is found, adds it to the actuator mask integer. +// --------------------------------------------------------------------------- +// +void CHWRMHapticsPluginManager::AddInfoIfSupportedL( TInt aMatch, + THWRMLogicalActuators aMask, + TUint32& aActuators ) + { + TInt pluginUid( 0 ); + User::LeaveIfError( iRepository->Get( aMatch, pluginUid ) ); + + // if the adaptation plugin UID is not zero, implementation is found, + // i.e. actuator is supported + if( pluginUid != 0 ) + { + // add actuator to the mask + aActuators = aActuators | aMask; + } + } + +// End of File