--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usbengines/usbwatcher/src/cusbwatcher.cpp Fri Jun 04 10:27:39 2010 +0100
@@ -0,0 +1,1082 @@
+/*
+* Copyright (c) 2006-2010 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: This implements CUsbWatcher class.
+*
+*/
+
+
+#include <ecom/ecom.h>
+#include <utf.h>
+#include <coreapplicationuisdomainpskeys.h>
+//CleanupResetAndDestroyPushL
+#include <mmf/common/mmfcontrollerpluginresolver.h>
+#include <UsbWatcherInternalCRKeys.h>
+#include <cusbpersonalitynotifier.h>
+#include <UsbWatcherInternalPSKeys.h>
+#include <e32property.h>
+#include <startupdomainpskeys.h> //for global system state
+
+#include "cusbwatcher.h"
+#include "cusbactivestate.h"
+#include "cusbactivepersonalityhandler.h"
+#include "cusbwatchersession.h"
+#include "cusbdevicelock.h"
+#include "cusbdevconstarter.h"
+#include "cusbglobalsystemstateobserver.h"
+#include "cusbotgwatcher.h"
+
+_LIT_SECURITY_POLICY_PASS( KAlwaysPassPolicy );
+_LIT_SECURITY_POLICY_C1( KLocalServicesPolicy, ECapabilityLocalServices );
+
+const TUint32 KUsbWatcherUseSerialNumber = 0x80000000;
+const TUint32 KUsbWatcherPersonalityIdMask = 0x0000FFFF;
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that might leave.
+// ----------------------------------------------------------------------------
+//
+CUsbWatcher::CUsbWatcher()
+ : CActive( EPriorityStandard )
+ {
+ LOG_FUNC
+
+ CActiveScheduler::Add( this );
+ }
+
+// ----------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::ConstructL()
+ {
+ LOG_FUNC
+
+ LEAVEIFERROR( RProperty::Define( KPSUidUsbWatcher,
+ KUsbWatcherSelectedPersonality, RProperty::EInt, KAlwaysPassPolicy,
+ KLocalServicesPolicy ) );
+
+ LEAVEIFERROR( RProperty::Set( KPSUidUsbWatcher,
+ KUsbWatcherSelectedPersonality,
+ KUsbWatcherSelectedPersonalityNone ) );
+
+ iPersonalityRepository = CRepository::NewL( KCRUidUsbWatcher );
+
+ LEAVEIFERROR( iPersonalityRepository->Get( KUsbWatcherPersonality,
+ iPersonalityId ) );
+ LOG1( "iPersonalityId from CenRep = %d", iPersonalityId );
+ iPrevPersonalityId = iPersonalityId;
+ iOldPrevPersonalityId = iPersonalityId;
+ LEAVEIFERROR( iUsbMan.Connect() );
+
+ TInt ret = iUsbMan.SetCtlSessionMode( ETrue );
+ if( KErrNone == ret )
+ {
+ LOG( "Creating CUsbOtgWatcher..." );
+ iOtgWatcher = CUsbOtgWatcher::NewL( iUsbMan );
+ }
+ else if( KErrNotSupported == ret )
+ {
+ LOG( "Non-OTG configuration detected!" );
+ }
+ else
+ {
+ LOG( "ERROR: is there another USB Control process? LEAVE" );
+ LEAVE( ret );
+ }
+
+ iPersonalityHandler
+ = CUsbActivePersonalityHandler::NewL( iUsbMan, *this );
+
+ GetPersonalityPluginsL();
+ iUsbDeviceLock = CUsbDeviceLock::NewL( *this );
+ iUsbDeviceLock->Subscribe();
+ iGlobalStateObserver = CUsbGlobalSystemStateObserver::NewL( *this );
+ iUsbDevConStarter = CUsbDevConStarter::NewL();
+ iActiveState = CUsbActiveState::NewL( iUsbMan, *this );
+ }
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+CUsbWatcher* CUsbWatcher::NewL()
+ {
+ LOG_FUNC
+
+ CUsbWatcher* self = new ( ELeave ) CUsbWatcher();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop(); // pop self
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// Destructor.
+// ----------------------------------------------------------------------------
+//
+CUsbWatcher::~CUsbWatcher()
+ {
+ LOG_FUNC
+
+ RProperty::Delete( KPSUidUsbWatcher, KUsbWatcherSelectedPersonality );
+
+ iUsbMan.Close();
+ iObservers.Reset();
+ if( iUsbDeviceLock )
+ {
+ iUsbDeviceLock->Cancel();
+ }
+ delete iActiveState;
+ delete iUsbDevConStarter;
+ delete iPersonalityHandler;
+ delete iPersonalityRepository;
+ delete iOtgWatcher;
+ delete iUsbDeviceLock;
+ delete iGlobalStateObserver;
+ iSupportedPersonalities.Close();
+ }
+
+// ----------------------------------------------------------------------------
+// Get personality plugins. Note that this is done only in normal mode.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::GetPersonalityPluginsL()
+ {
+ LOG_FUNC
+
+ // Get personality plugins
+ RImplInfoPtrArray implementations;
+ CleanupResetAndDestroyPushL( implementations );
+
+ const TEComResolverParams noResolverParams;
+
+ REComSession::ListImplementationsL( KUidPersonalityPlugIns,
+ noResolverParams, KRomOnlyResolverUid, implementations );
+ TInt personalityNum = implementations.Count();
+ LOG1( "Number of PersonalityPlugin(s): %d", personalityNum );
+
+ if( personalityNum < 1 )
+ {
+ LOG( "No PersonalityPlugin available. LEAVE" );
+ LEAVE( KErrGeneral );
+ }
+
+ for( TInt i = 0; i < personalityNum; i++ )
+ {
+ TUsbSupportedPersonalityInf inf;
+ TLex8 lex;
+ TUint32 confValue;
+
+ // save implementation uid
+ inf.iPersonalityUid = implementations[i]->ImplementationUid();
+ lex.Assign( implementations[i]->DataType() );
+
+ if( lex.Val( confValue, EHex ) != KErrNone )
+ {
+ CleanupStack::PopAndDestroy( &implementations );
+ iSupportedPersonalities.Close();
+ LEAVE( KErrGeneral );
+ }
+
+ // check whether personality requires serial number
+ if( confValue & KUsbWatcherUseSerialNumber )
+ {
+ inf.iUseSerialNumber = ETrue;
+ }
+ else
+ {
+ inf.iUseSerialNumber = EFalse;
+ }
+
+ // save personality id
+ inf.iPersonalityId = static_cast<TInt>( ( KUsbWatcherPersonalityIdMask
+ & confValue ) );
+
+ LOG1( "PersonalityId = %d" , inf.iPersonalityId );
+
+ iSupportedPersonalities.AppendL( inf );
+ }
+
+ CleanupStack::PopAndDestroy( &implementations );
+ }
+
+// ----------------------------------------------------------------------------
+// This method notifies CUsbWatcher class about USB state changes.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::StateChangeNotify( TUsbDeviceState aStateOld,
+ TUsbDeviceState aStateNew )
+ {
+ LOG_FUNC
+
+ // Handling USB indicator. This is valid for both A- and B-device cases.
+ // Not show USB indicator in charging mode
+ if ( iNormalStart )
+ {
+ iUsbIndicatorHandler.HandleDeviceStateChange( aStateOld, aStateNew );
+ }
+
+ if ( IsDeviceA() ) // Will be handled by UsbOtgWatcher
+ {
+ LOG( "Device state change ignored by UsbWatcher in A-device state" );
+ return;
+ }
+
+ LOG1( "WatcherState = %d", iState );
+
+ // Notify personality handler first
+ switch( aStateNew )
+ {
+ case EUsbDeviceStatePowered:
+ // Case for Attached state missed
+ // NO break here;
+ case EUsbDeviceStateAttached:
+ {
+ if( EUsbDeviceStateUndefined != aStateOld )
+ {
+ LOG1( "Not starting personality, previous state: %d",
+ aStateOld);
+ break;
+ }
+ LOG1( "Starting USB personality in device state: %d", aStateNew );
+ iPersonalityHandler->StateChangeNotify( aStateOld, aStateNew );
+ // Check AskOnConnection setting every time
+ if( ( iSupportedPersonalities.Count() > 1 ) &&
+ !IsAskOnConnectionSuppression() )
+ {
+ // read setting if there is more than one personality
+ iPersonalityRepository->Get(
+ KUsbWatcherChangeOnConnectionSetting,
+ iAskOnConnectionSetting );
+ }
+
+ if( ( iState == EUsbIdle ) && !iPersonalityChangeOngoing )
+ {
+ Start();
+ }
+ else if( ( iState != EUsbStarted ) && !iPersonalityChangeOngoing )
+ {
+ Cancel();
+ Start();
+ }
+
+ // Let's turn ask on connection off after start cause we will
+ // issue it only when cable is connected
+ iAskOnConnectionSetting = KUsbWatcherChangeOnConnectionOff;
+
+ //start usbdevcon only in normal global state
+ TInt globalState =
+ CUsbGlobalSystemStateObserver::GlobalSystemState();
+ if( ( ESwStateNormalRfOn == globalState ) ||
+ ( ESwStateNormalRfOff == globalState ) ||
+ ( ESwStateNormalBTSap == globalState ) )
+ {
+ iUsbDevConStarter->Start();
+ }
+ }
+ break;
+
+ case EUsbDeviceStateUndefined:
+ {
+ iGlobalStateObserver->Cancel();
+ // Notify clients currently loaded personality will be unloaded
+ iPersonalityHandler->StateChangeNotify( aStateOld, aStateNew );
+ iUsbDevConStarter->StopRestarting();
+ // This must be done before Notify()
+ if( iSetPreviousPersonalityOnDisconnect )
+ {
+ TInt temp = iPersonalityId;
+ iPersonalityId = iPrevPersonalityId;
+ iPrevPersonalityId = temp;
+ WritePersonalityId( iPersonalityId );
+ iSetPreviousPersonalityOnDisconnect = EFalse;
+ }
+
+ Notify( KErrCancel );
+ if (iState == EUsbStarting)
+ {
+ LOG( "StartCancel USB" );
+ Cancel();
+ }
+ else
+ {
+ LOG( "Stop USB" );
+
+ if( EUsbConfirmStop == iState )
+ {
+ // We have request pending on personality handler
+ Cancel();
+ }
+
+ Stop();
+ }
+ }
+ break;
+
+ default:
+ if ( EUsbStarted == iState )
+ {
+ iPersonalityHandler->StateChangeNotify( aStateOld, aStateNew );
+ }
+ break;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// From class CActive.
+// This method cancels any outstanding request.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::DoCancel()
+ {
+ LOG_FUNC
+
+ LOG1( "WatcherState = %d", iState );
+ if( ( EUsbStarting == iState ) || ( EUsbStopping == iState ) )
+ {
+ iPersonalityHandler->Cancel();
+
+ RProperty::Set( KPSUidUsbWatcher,
+ KUsbWatcherSelectedPersonality,
+ KUsbWatcherSelectedPersonalityNone );
+ LOG( "personality set to none" );
+
+ iState = EUsbIdle;
+ }
+ else if( EUsbConfirmStop == iState )
+ {
+ iPersonalityHandler->Cancel();
+ iState = EUsbStarted;
+ }
+ else
+ {
+ LOG( "Nothingh to cancel" );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// This method implements state machine for personality start and stop.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::RunL()
+ {
+ LOG_FUNC
+
+ LOG1( "WatcherState = %d", iState );
+ TInt ret = iStatus.Int();
+ if ( KErrNone != ret )
+ {
+ LOG1( "ERROR: CUsbWatcher::RunL iStatus = %d", ret );
+ }
+
+ switch ( iState )
+ {
+ case EUsbStarting:
+ LOG( "Personality started" );
+ Notify( ret );
+ if( iStopStartScenario )
+ {
+ iStopStartScenario = EFalse;
+ }
+ //check if StartPersonality() fails
+ LEAVEIFERROR( ret );
+ iState = EUsbStarted;
+ break;
+
+ case EUsbStopping:
+ LOG( "Personality stopped" );
+ iState = EUsbIdle;
+ if( iStopStartScenario )
+ {
+ Start();
+ }
+ else
+ {
+ RProperty::Set( KPSUidUsbWatcher,
+ KUsbWatcherSelectedPersonality,
+ KUsbWatcherSelectedPersonalityNone );
+ }
+ break;
+
+ case EUsbStarted:
+ if( iStopStartScenario )
+ {
+ break;
+ }
+
+ iPersonalityHandler->StopPersonality( iStatus );
+ SetActive();
+ iState = EUsbStopping;
+ break;
+
+ case EUsbIdle:
+ if( iStopStartScenario )
+ {
+ Start();
+ }
+ break;
+
+ case EUsbConfirmStop:
+ if( iStatus == KErrNone )
+ {
+ iStopStartScenario = ETrue;
+ iPersonalityHandler->StopPersonality( iStatus );
+ SetActive();
+ iState = EUsbStopping;
+ }
+ else
+ {
+ Notify( ret );
+ iState = EUsbStarted;
+ }
+ break;
+
+ default:
+ LOG( "ERROR: unexpected state" );
+ PANIC( KErrGeneral );
+ break;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// This method is not called cause RunL() never leaves.
+// ----------------------------------------------------------------------------
+//
+TInt CUsbWatcher::RunError(TInt aError)
+ {
+ LOG_FUNC
+
+ LOG2("Returned error: %d, iState: %d", aError, iState);
+ if ( iState == EUsbStarting )
+ {
+ RProperty::Set( KPSUidUsbWatcher,
+ KUsbWatcherSelectedPersonality,
+ KUsbWatcherSelectedPersonalityNone );
+ LOG( "personality set to none" );
+
+ iState = EUsbIdle;
+ }
+
+ return KErrNone;
+ }
+
+// ----------------------------------------------------------------------------
+// Function is called when state of the device is locked.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::Lock()
+ {
+ LOG_FUNC
+
+ if( IsDeviceA() ) // Not applicable in case of A-device
+ {
+ LOG( "Lock ignored in A-device state" );
+ return;
+ }
+
+
+ TUsbDeviceState state = iActiveState->CurrentState();
+
+ LOG1( "USB device state after lock: %d", state );
+
+ if( EUsbDeviceStateUndefined != state ) // Stop personality
+ {
+ LOG( "Stopping USB persoanlity on device remote-lock" );
+
+ iPersonalityHandler->CancelCableConnectedNotifier();
+
+ if( iState != EUsbStarted )
+ {
+ Cancel();
+ }
+ else
+ {
+ Stop();
+ }
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Function is called when state of the device is unlocked.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::Unlock()
+ {
+ LOG_FUNC
+
+ if( IsDeviceA() ) // Not applicable in case of A-device
+ {
+ LOG( "Unlock ignored in A-device state" );
+ return;
+ }
+
+ TUsbDeviceState state = iActiveState->CurrentState();
+
+ LOG1( "USB device state after unlock: %d", state );
+ if( EUsbDeviceStateAttached == state || EUsbDeviceStatePowered == state)
+ {
+ LOG( "Starting USB personality" );
+ TInt err = iPersonalityRepository->Get(
+ KUsbWatcherChangeOnConnectionSetting, iAskOnConnectionSetting );
+ if( KErrNone == err )
+ {
+ Start();
+ iAskOnConnectionSetting = KUsbWatcherChangeOnConnectionOff;
+ }
+ else
+ {
+ LOG1( "Error: CRepository::Get = %d", err );
+ }
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// This method is called when client wants to set new personality.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::SetPersonality( TInt aPersonalityId, TBool aNonBlocking )
+ {
+ LOG_FUNC
+
+ LOG2( "aPersonalityId=%d, aNonBlocking=%d", aPersonalityId, aNonBlocking );
+
+ // Check if personality is exist
+ TBool found = EFalse;
+
+ for( TInt i = 0; i < iSupportedPersonalities.Count(); i++ )
+ {
+ if( iSupportedPersonalities[i].iPersonalityId == aPersonalityId )
+ {
+ found = ETrue;
+ }
+ }
+
+ if( !found )
+ {
+ Notify( KErrNotFound );
+ return;
+ }
+
+ iSetPersonalityOngoing = ETrue;
+ iPersonalityChangeOngoing = ETrue;
+
+ //The previous personality is not changed, if the client wanted the
+ //previous personality change to be temporary. The client has to call
+ //SetPreviousPersonalityOnDisconnect after each SetPersonality to be
+ //intended as temporary.
+ if( iSetPreviousPersonalityOnDisconnect )
+ {
+ iSetPreviousPersonalityOnDisconnect = EFalse;
+ }
+ else
+ {
+ iOldPrevPersonalityId = iPrevPersonalityId;
+ iPrevPersonalityId = iPersonalityId;
+ LOG( "CUsbWatcher::SetPersonality setting previous" );
+ }
+ LOG1( " iPrevPersonalityId = %d", iPrevPersonalityId );
+ if( iPersonalityId != aPersonalityId )
+ {
+ iPersonalityId = aPersonalityId;
+ SwitchPersonality( aNonBlocking );
+ }
+ else
+ {
+ Notify( KErrNone );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// This method is called when client wants to cancel set personality.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::CancelSetPersonality()
+ {
+ LOG_FUNC
+
+ Notify( KErrCancel );
+ iPersonalityChangeOngoing = ETrue;
+ iStopStartScenario = EFalse;
+ SwitchPersonality();
+ }
+
+// ----------------------------------------------------------------------------
+// This method is called when client wants to set previous personality.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::SetPreviousPersonality()
+ {
+ LOG_FUNC
+
+ if( IsDeviceA() )
+ {
+ LOG( "SetPreviousPersonality not allowed in A-device state" );
+ Notify( KErrAccessDenied );
+ return;
+ }
+
+ TInt temp = iPersonalityId;
+ iSetPreviousPersonalityOnDisconnect = EFalse;
+
+ iPersonalityId = iPrevPersonalityId;
+ iPrevPersonalityId = temp;
+ iSetPreviousPersonalityOngoing = ETrue;
+ iPersonalityChangeOngoing = ETrue;
+
+ if( iPersonalityId != iPrevPersonalityId )
+ {
+ SwitchPersonality();
+ }
+ else
+ {
+ Notify( KErrNone );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// This method is called when client wants to cancel set previous personality.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::CancelSetPreviousPersonality()
+ {
+ LOG_FUNC
+
+ Notify( KErrCancel );
+ iPersonalityChangeOngoing = ETrue;
+ iStopStartScenario = EFalse;
+ SwitchPersonality();
+ }
+
+// ----------------------------------------------------------------------------
+// This method is called when client wants to set previous personality on
+// disconnect.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::SetPreviousPersonalityOnDisconnect()
+ {
+ LOG_FUNC
+
+ if( IsDeviceA() )
+ {
+ LOG( "Not allowed in A-device state" );
+ Notify( KErrAccessDenied );
+ return;
+ }
+
+ TUsbDeviceState state = iActiveState->CurrentState();
+ LOG1( "Device state : %d", state );
+ if( state != EUsbDeviceStateUndefined )
+ {
+ iSetPreviousPersonalityOnDisconnect = ETrue;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// This method starts personality change, if there is cable connected.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::SwitchPersonality( TBool aNonBlocking )
+ {
+ LOG_FUNC
+
+
+ TUsbDeviceState state = iActiveState->CurrentState();
+ LOG2( "IsDeviceA: %d, Device state : %d", IsDeviceA(), state );
+
+ // As A-device, only cenrep will be updated for the reasons of
+ // - In A-host state, device state will be undefined
+ // - In A-peripheral state, personality change can not happen otherwise
+ // the connection will be lost
+ if ( IsDeviceA() || ( EUsbDeviceStateUndefined == state ) )
+ {
+ // if no connection -> just save the setting
+ LOG( "CUsbWatcher::SwitchPersonality: Notify" );
+ Notify( KErrNone );
+ }
+ else
+ {
+ switch ( iState )
+ {
+ case EUsbStopping:
+ case EUsbStarting:
+ {
+ LOG( "CUsbWatcher::SwitchPersonality: Cancel & Start USB" );
+ Cancel();
+ Start();
+ }
+ break;
+ case EUsbConfirmStop:
+ {
+ Cancel();
+ iState = EUsbStarted;
+ StopStart( aNonBlocking );
+ }
+ break;
+ case EUsbStarted:
+ {
+ LOG( "CUsbWatcher::SwitchPersonality: Stop & Start USB" );
+ StopStart( aNonBlocking );
+ }
+ break;
+ default:
+ {
+ LOG( "CUsbWatcher::SwitchPersonality: Start USB" );
+ Start();
+ }
+ break;
+ }
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// This method starts personality loading or continues stop start scenario.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::Start()
+ {
+ LOG_FUNC
+
+ TInt globalState = CUsbGlobalSystemStateObserver::GlobalSystemState();
+
+ if( iState == EUsbIdle )
+ {
+ iStarted = EFalse;
+ iNormalStart = EFalse;
+ if( globalState == ESwStateCharging )
+ {
+ LOG( "Global state: charging" );
+ iGlobalStateObserver->Subscribe();
+ iPrevPersonalityId=iPersonalityId;
+ TInt ret = GetChargingPersonalityId( iPersonalityId );
+ //do not start if charging personality not assigned
+ if( KErrNone == ret )
+ {
+ RProperty::Set( KPSUidUsbWatcher,
+ KUsbWatcherSelectedPersonality, iPersonalityId );
+ iStarted = ETrue;
+ // Restore personality to normal in charging mode
+ iSetPreviousPersonalityOnDisconnect = ETrue;
+ iPersonalityHandler->StartPersonality( iPersonalityId,
+ KUsbWatcherChangeOnConnectionOff, iStatus );
+ }
+ else
+ {
+ LOG1( "GetChargingPersonalityId = %d. Not started", ret );
+ }
+ }
+ else if( ( ( ESwStateNormalRfOn == globalState ) ||
+ ( ESwStateNormalRfOff == globalState ) ||
+ ( ESwStateNormalBTSap == globalState ) ))
+ {
+ LOG( "Global state: normal" );
+ iNormalStart = ETrue;
+ if( ! iUsbDeviceLock->Locked() )
+ {
+ iGlobalStateObserver->Cancel();
+ RProperty::Set( KPSUidUsbWatcher,
+ KUsbWatcherSelectedPersonality, iPersonalityId );
+ iStarted = ETrue;
+ iPersonalityHandler->StartPersonality( iPersonalityId,
+ iAskOnConnectionSetting, iStatus );
+ }
+ else
+ {
+ LOG( "Device LOCKED, USB personality NOT start" );
+ }
+ }
+ else
+ {
+ LOG1( "Global state: = %d", globalState );
+ //Cable connected in e.g. ChargingToNormal state and
+ // personality started later in a normal state.
+ iGlobalStateObserver->Subscribe();
+ }
+ if( iStarted )
+ {
+ SetActive();
+ iState = EUsbStarting;
+ }
+ }
+ else
+ {
+ LOG( "Tryign to call CUsbWatcher::Start in non-idle state " );
+ PANIC( KErrGeneral );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// This method starts personality unloading or cancels personality start.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::Stop()
+ {
+ LOG_FUNC
+
+ LOG1( "WatcherState = %d", iState );
+ if( EUsbStarted == iState )
+ {
+ iPersonalityHandler->StopPersonality( iStatus );
+ SetActive();
+ iState = EUsbStopping;
+
+ }
+ else if( EUsbStarting == iState )
+ {
+ LOG( "Cancel ongoing start." );
+ Cancel();
+ }
+
+ else
+ {
+ LOG( "Wrong state for Stop" );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// This method is used when there is need to change currently loaded
+// personality.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::StopStart( TBool aNonBlocking )
+ {
+ LOG_FUNC
+
+ LOG1( "WatcherState = %d", iState );
+ if( iState == EUsbStarted )
+ {
+ iState = EUsbConfirmStop;
+ if( !aNonBlocking )
+ {
+ iPersonalityHandler->ConfirmPersonalityUnload( iStatus );
+ SetActive();
+ }
+ else
+ {
+ LOG( "CUsbWatcher::StopStart not confirming" );
+ SetActive();
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone );
+ }
+ }
+ else
+ {
+ LOG( "Wrong state to StopStart" );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CUsbWatcherSession uses this method to register observer.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::RegisterObserverL( MUsbWatcherNotify* aObserver )
+ {
+ LOG_FUNC
+
+ TInt index = iObservers.Find( aObserver );
+ if( index < 0 )
+ {
+ iObservers.AppendL( aObserver );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CUsbWatcherSession uses this method to deregister observer.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::DeRegisterObserver( MUsbWatcherNotify* aObserver )
+ {
+ LOG_FUNC
+
+ TInt index = iObservers.Find( aObserver );
+
+ if( index >= 0 )
+ {
+ iObservers.Remove( index );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// This method is used to complete any outstanding request.
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::Notify( TInt aStatus )
+ {
+ LOG_FUNC
+
+ LOG1( "aStatus = %d", aStatus );
+ TInt status = aStatus;
+
+ // clear every time when notified
+ iPersonalityChangeOngoing = EFalse;
+
+ if( iSetPersonalityOngoing || iChangePersonalityOngoing )
+ {
+ iSetPersonalityOngoing = EFalse;
+ iChangePersonalityOngoing = EFalse;
+
+ if( status == KErrNone )
+ {
+ status = WritePersonalityId( iPersonalityId );
+ }
+ else
+ {
+ // in case of error return to state before SetPersonality
+ iPersonalityId = iPrevPersonalityId;
+ iPrevPersonalityId = iOldPrevPersonalityId;
+ }
+ }
+
+ if( iSetPreviousPersonalityOngoing )
+ {
+ iSetPreviousPersonalityOngoing = EFalse;
+
+ if( status == KErrNone )
+ {
+ WritePersonalityId( iPersonalityId );
+ }
+ else
+ {
+ // in case of error return to state before SetPreviousPersonality
+ TInt temp = iPrevPersonalityId;
+
+ iPrevPersonalityId = iPersonalityId;
+ iPersonalityId = temp;
+ }
+ }
+
+ for( TInt i = 0; i < iObservers.Count(); i++ )
+ {
+ iObservers[i]->Notify( iPersonalityId, status );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Stop loaded personality. Called from global state handler
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::StopPersonality()
+ {
+ LOG_FUNC
+ // restore settings
+ iPersonalityId = iPrevPersonalityId;
+
+ Stop();
+ iStarted = EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+// Start personality. Called from global state handler
+// ----------------------------------------------------------------------------
+//
+void CUsbWatcher::StartPersonality()
+ {
+ LOG_FUNC
+
+ if( !iStarted )
+ {
+ Start();
+ }
+
+ //start usbdevcon only in normal global state
+ TInt globalState = CUsbGlobalSystemStateObserver::GlobalSystemState();
+ if( ( globalState == ESwStateNormalRfOn ) ||
+ ( globalState == ESwStateNormalRfOff ) ||
+ ( globalState == ESwStateNormalBTSap ) )
+ {
+ iUsbDevConStarter->Start();
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Read default personality from ini file. Used in charging mode
+// ----------------------------------------------------------------------------
+//
+TInt CUsbWatcher::GetChargingPersonalityId( TInt& aPersonalityId )
+ {
+ LOG_FUNC
+
+ TInt ret = iPersonalityRepository->Get(
+ KUsbWatcherChargingDefaultPersonality, aPersonalityId );
+ return ret;
+ }
+
+// ----------------------------------------------------------------------------
+// Check if there is an observer with ask on connection suppression
+// ----------------------------------------------------------------------------
+//
+TBool CUsbWatcher::IsAskOnConnectionSuppression()
+ {
+ LOG_FUNC
+
+ TBool ret( EFalse );
+ for( TInt i = 0; i < iObservers.Count(); i++ )
+ {
+ if( iObservers[i]->IsAskOnConnectionSuppressed() )
+ {
+ ret = ETrue;
+ break;
+ }
+ }
+ LOG1( "Return = %d", ret );
+ return ret;
+ }
+
+// ----------------------------------------------------------------------------
+// Check current A or B device state
+// ----------------------------------------------------------------------------
+//
+TBool CUsbWatcher::IsDeviceA()
+ {
+ //NOT LOGGED
+ // return EFalse in non-OTG configuration otherwise ask UsbOtgWatcher
+ return iOtgWatcher ? iOtgWatcher->IsDeviceA() : EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+// Write new personality to central repository.
+// ----------------------------------------------------------------------------
+//
+TInt CUsbWatcher::WritePersonalityId( TInt aPersonalityId )
+ {
+ LOG_FUNC
+
+ // Save as the default personality only if it is not hidden
+ TUint32 property(0);
+ TInt ret = iUsbMan.GetPersonalityProperty( aPersonalityId, property );
+ if ( ret == KErrNone )
+ {
+ LOG2( "Personality %d property: 0x%x", aPersonalityId, property );
+ }
+ else
+ {
+ //Not fatal, treat as non-hidden
+ LOG1( "ERROR: GetPersonalityProperty = %d", ret );
+ property = 0;
+ }
+ if ( property & KUsbPersonalityPropertyHidden ) //Bitwise AND
+ {
+ LOG( "Hidden personality not saved to central repository" );
+ ret = KErrNone;
+ }
+ else
+ {
+ ret = iPersonalityRepository->Set( KUsbWatcherPersonality,
+ aPersonalityId );
+ }
+ return ret;
+ }
+
+// End of file