usbengines/usbwatcher/src/cusbwatcher.cpp
changeset 35 9d8b04ca6939
child 38 218231f2b3b3
equal deleted inserted replaced
34:7858bc6ead78 35:9d8b04ca6939
       
     1 /*
       
     2 * Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  This implements CUsbWatcher class.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <ecom/ecom.h>
       
    20 #include <utf.h>
       
    21 #include <coreapplicationuisdomainpskeys.h>
       
    22 //CleanupResetAndDestroyPushL
       
    23 #include <mmf/common/mmfcontrollerpluginresolver.h>
       
    24 #include <UsbWatcherInternalCRKeys.h>
       
    25 #include <cusbpersonalitynotifier.h>
       
    26 #include <UsbWatcherInternalPSKeys.h>
       
    27 #include <e32property.h>
       
    28 #include <startupdomainpskeys.h> //for global system state
       
    29 
       
    30 #include "cusbwatcher.h"
       
    31 #include "cusbactivestate.h"
       
    32 #include "cusbactivepersonalityhandler.h"
       
    33 #include "cusbwatchersession.h"
       
    34 #include "cusbdevicelock.h"
       
    35 #include "cusbdevconstarter.h"
       
    36 #include "cusbglobalsystemstateobserver.h"
       
    37 #include "cusbotgwatcher.h"
       
    38 
       
    39 _LIT_SECURITY_POLICY_PASS( KAlwaysPassPolicy );
       
    40 _LIT_SECURITY_POLICY_C1( KLocalServicesPolicy, ECapabilityLocalServices );
       
    41 
       
    42 const TUint32 KUsbWatcherUseSerialNumber = 0x80000000;
       
    43 const TUint32 KUsbWatcherPersonalityIdMask = 0x0000FFFF;
       
    44 
       
    45 // ============================ MEMBER FUNCTIONS ==============================
       
    46 
       
    47 // ----------------------------------------------------------------------------
       
    48 // C++ default constructor can NOT contain any code, that might leave.
       
    49 // ----------------------------------------------------------------------------
       
    50 //
       
    51 CUsbWatcher::CUsbWatcher()
       
    52     : CActive( EPriorityStandard )
       
    53     {
       
    54     LOG_FUNC
       
    55 
       
    56     CActiveScheduler::Add( this );
       
    57     }
       
    58 
       
    59 // ----------------------------------------------------------------------------
       
    60 // Symbian 2nd phase constructor can leave.
       
    61 // ----------------------------------------------------------------------------
       
    62 //
       
    63 void CUsbWatcher::ConstructL()
       
    64     {
       
    65     LOG_FUNC
       
    66 
       
    67     LEAVEIFERROR( RProperty::Define( KPSUidUsbWatcher,
       
    68             KUsbWatcherSelectedPersonality, RProperty::EInt, KAlwaysPassPolicy,
       
    69             KLocalServicesPolicy ) );
       
    70 
       
    71     LEAVEIFERROR( RProperty::Set( KPSUidUsbWatcher,
       
    72             KUsbWatcherSelectedPersonality,
       
    73             KUsbWatcherSelectedPersonalityNone ) );
       
    74 
       
    75     iPersonalityRepository = CRepository::NewL( KCRUidUsbWatcher );
       
    76 
       
    77     LEAVEIFERROR( iPersonalityRepository->Get( KUsbWatcherPersonality,
       
    78             iPersonalityId ) );
       
    79     LOG1( "iPersonalityId from CenRep = %d", iPersonalityId );
       
    80     iPrevPersonalityId = iPersonalityId;
       
    81     iOldPrevPersonalityId = iPersonalityId;
       
    82     LEAVEIFERROR( iUsbMan.Connect() );
       
    83 
       
    84     TInt ret = iUsbMan.SetCtlSessionMode( ETrue );
       
    85     if( KErrNone == ret )
       
    86         {
       
    87         LOG( "Creating CUsbOtgWatcher..."  );
       
    88         iOtgWatcher = CUsbOtgWatcher::NewL( iUsbMan );
       
    89         }
       
    90     else if( KErrNotSupported == ret )
       
    91         {
       
    92         LOG( "Non-OTG configuration detected!"  );
       
    93         }
       
    94     else
       
    95         {
       
    96         LOG( "ERROR: is there another USB Control process? LEAVE" );
       
    97         LEAVE( ret );
       
    98         }
       
    99 
       
   100     iPersonalityHandler
       
   101         = CUsbActivePersonalityHandler::NewL( iUsbMan, *this );
       
   102 
       
   103     GetPersonalityPluginsL();
       
   104     iUsbDeviceLock = CUsbDeviceLock::NewL( *this );
       
   105     iUsbDeviceLock->Subscribe();
       
   106     iGlobalStateObserver = CUsbGlobalSystemStateObserver::NewL( *this );
       
   107     iUsbDevConStarter = CUsbDevConStarter::NewL();
       
   108     iActiveState = CUsbActiveState::NewL( iUsbMan, *this );
       
   109     }
       
   110 
       
   111 // ----------------------------------------------------------------------------
       
   112 // Two-phased constructor.
       
   113 // ----------------------------------------------------------------------------
       
   114 //
       
   115 CUsbWatcher* CUsbWatcher::NewL()
       
   116     {
       
   117     LOG_FUNC
       
   118 
       
   119     CUsbWatcher* self = new ( ELeave ) CUsbWatcher();
       
   120     CleanupStack::PushL( self );
       
   121     self->ConstructL();
       
   122     CleanupStack::Pop(); // pop self
       
   123     return self;
       
   124     }
       
   125 
       
   126 // ----------------------------------------------------------------------------
       
   127 // Destructor.
       
   128 // ----------------------------------------------------------------------------
       
   129 //
       
   130 CUsbWatcher::~CUsbWatcher()
       
   131     {
       
   132     LOG_FUNC
       
   133 
       
   134     RProperty::Delete( KPSUidUsbWatcher, KUsbWatcherSelectedPersonality );
       
   135 
       
   136     iUsbMan.Close();
       
   137     iObservers.Reset();
       
   138     if( iUsbDeviceLock )
       
   139         {
       
   140         iUsbDeviceLock->Cancel();
       
   141         }
       
   142     delete iActiveState;
       
   143     delete iUsbDevConStarter;
       
   144     delete iPersonalityHandler;
       
   145     delete iPersonalityRepository;
       
   146     delete iOtgWatcher;
       
   147     delete iUsbDeviceLock;
       
   148     delete iGlobalStateObserver;
       
   149     iSupportedPersonalities.Close();
       
   150     }
       
   151 
       
   152 // ----------------------------------------------------------------------------
       
   153 // Get personality plugins. Note that this is done only in normal mode.
       
   154 // ----------------------------------------------------------------------------
       
   155 //
       
   156 void CUsbWatcher::GetPersonalityPluginsL()
       
   157     {
       
   158     LOG_FUNC
       
   159     
       
   160     // Get personality plugins
       
   161     RImplInfoPtrArray implementations;
       
   162     CleanupResetAndDestroyPushL( implementations );
       
   163 
       
   164     const TEComResolverParams noResolverParams;
       
   165 
       
   166     REComSession::ListImplementationsL( KUidPersonalityPlugIns,
       
   167             noResolverParams, KRomOnlyResolverUid, implementations );
       
   168     TInt personalityNum = implementations.Count();
       
   169     LOG1( "Number of PersonalityPlugin(s): %d", personalityNum );
       
   170     
       
   171     if( personalityNum < 1 )
       
   172         {
       
   173         LOG( "No PersonalityPlugin available. LEAVE" );
       
   174         LEAVE( KErrGeneral );
       
   175         }
       
   176 
       
   177     for( TInt i = 0; i < personalityNum; i++ )
       
   178         {
       
   179         TUsbSupportedPersonalityInf inf;
       
   180         TLex8 lex;
       
   181         TUint32 confValue;
       
   182 
       
   183         // save implementation uid
       
   184         inf.iPersonalityUid = implementations[i]->ImplementationUid();
       
   185         lex.Assign( implementations[i]->DataType() );
       
   186 
       
   187         if( lex.Val( confValue, EHex ) != KErrNone )
       
   188             {
       
   189             CleanupStack::PopAndDestroy( &implementations );
       
   190             iSupportedPersonalities.Close();
       
   191             LEAVE( KErrGeneral );
       
   192             }
       
   193 
       
   194         // check whether personality requires serial number
       
   195         if( confValue & KUsbWatcherUseSerialNumber )
       
   196             {
       
   197             inf.iUseSerialNumber = ETrue;
       
   198             }
       
   199         else
       
   200             {
       
   201             inf.iUseSerialNumber = EFalse;
       
   202             }
       
   203 
       
   204         // save personality id
       
   205         inf.iPersonalityId = static_cast<TInt>( ( KUsbWatcherPersonalityIdMask
       
   206                 & confValue ) );
       
   207 
       
   208         LOG1( "PersonalityId = %d" , inf.iPersonalityId );
       
   209 
       
   210         iSupportedPersonalities.AppendL( inf );
       
   211         }
       
   212 
       
   213     CleanupStack::PopAndDestroy( &implementations );
       
   214     }
       
   215 
       
   216 // ----------------------------------------------------------------------------
       
   217 // This method notifies CUsbWatcher class about USB state changes.
       
   218 // ----------------------------------------------------------------------------
       
   219 //
       
   220 void CUsbWatcher::StateChangeNotify( TUsbDeviceState aStateOld,  
       
   221         TUsbDeviceState aStateNew )
       
   222     {
       
   223     LOG_FUNC
       
   224 
       
   225     // Handling USB indicator. This is valid for both A- and B-device cases.
       
   226     // Not show USB indicator in charging mode
       
   227     if ( iNormalStart ) 
       
   228         {
       
   229         iUsbIndicatorHandler.HandleDeviceStateChange( aStateOld, aStateNew );
       
   230         }
       
   231         
       
   232     if ( IsDeviceA() ) // Will be handled by UsbOtgWatcher
       
   233         {
       
   234         LOG( "Device state change ignored by UsbWatcher in A-device state" );
       
   235         return;
       
   236         }
       
   237 
       
   238     LOG1( "WatcherState = %d", iState );
       
   239         
       
   240     // Notify personality handler first
       
   241     switch( aStateNew )
       
   242         {
       
   243         case EUsbDeviceStatePowered:
       
   244             // Case for Attached state missed 
       
   245             // NO break here;
       
   246         case EUsbDeviceStateAttached:
       
   247             {
       
   248             if( EUsbDeviceStateUndefined != aStateOld )
       
   249                 {
       
   250                 LOG1( "Not starting personality, previous state: %d", 
       
   251                     aStateOld);
       
   252                 break;
       
   253                 }
       
   254             LOG1( "Starting USB personality in device state: %d", aStateNew );
       
   255             iPersonalityHandler->StateChangeNotify( aStateOld, aStateNew );
       
   256             // Check AskOnConnection setting every time
       
   257             if( ( iSupportedPersonalities.Count() > 1 ) &&
       
   258                     !IsAskOnConnectionSuppression() )
       
   259                 {
       
   260                 // read setting if there is more than one personality
       
   261                 iPersonalityRepository->Get(
       
   262                         KUsbWatcherChangeOnConnectionSetting,
       
   263                         iAskOnConnectionSetting );
       
   264                 }
       
   265 
       
   266             if( ( iState == EUsbIdle ) && !iPersonalityChangeOngoing )
       
   267                 {
       
   268                 Start();
       
   269                 }
       
   270             else if( ( iState != EUsbStarted ) && !iPersonalityChangeOngoing )
       
   271                 {
       
   272                 Cancel();
       
   273                 Start();
       
   274                 }
       
   275 
       
   276             // Let's turn ask on connection off after start cause we will
       
   277             // issue it only when cable is connected
       
   278             iAskOnConnectionSetting = KUsbWatcherChangeOnConnectionOff;
       
   279 
       
   280             //start usbdevcon only in normal global state
       
   281             TInt globalState =
       
   282                     CUsbGlobalSystemStateObserver::GlobalSystemState();
       
   283             if( ( ESwStateNormalRfOn == globalState ) ||
       
   284                     ( ESwStateNormalRfOff == globalState ) ||
       
   285                     ( ESwStateNormalBTSap == globalState ) )
       
   286                 {
       
   287                 iUsbDevConStarter->Start();
       
   288                 }
       
   289             }
       
   290             break;
       
   291 
       
   292         case EUsbDeviceStateUndefined:
       
   293             {
       
   294             iGlobalStateObserver->Cancel();
       
   295             // Notify clients currently loaded personality will be unloaded
       
   296             iPersonalityHandler->StateChangeNotify( aStateOld, aStateNew );
       
   297             iUsbDevConStarter->StopRestarting();
       
   298             // This must be done before Notify()
       
   299             if( iSetPreviousPersonalityOnDisconnect )
       
   300                 {
       
   301                 TInt temp = iPersonalityId;
       
   302                 iPersonalityId = iPrevPersonalityId;
       
   303                 iPrevPersonalityId = temp;
       
   304                 WritePersonalityId( iPersonalityId );
       
   305                 iSetPreviousPersonalityOnDisconnect = EFalse;
       
   306                 }
       
   307 
       
   308             Notify( KErrCancel );
       
   309             if (iState == EUsbStarting)
       
   310                 {
       
   311                 LOG( "StartCancel USB" );
       
   312                 Cancel();
       
   313                 }
       
   314             else
       
   315                 {
       
   316                 LOG( "Stop USB" );
       
   317                 
       
   318                 if( EUsbConfirmStop == iState )
       
   319                     {
       
   320                     // We have request pending on personality handler
       
   321                     Cancel();
       
   322                     }
       
   323                 
       
   324                     Stop();
       
   325                     }
       
   326             }
       
   327             break;
       
   328 
       
   329         default:
       
   330             if ( EUsbStarted == iState )
       
   331                 {
       
   332                 iPersonalityHandler->StateChangeNotify( aStateOld, aStateNew );
       
   333                 }
       
   334             break;
       
   335         }
       
   336     }
       
   337 
       
   338 // ----------------------------------------------------------------------------
       
   339 // From class CActive.
       
   340 // This method cancels any outstanding request.
       
   341 // ----------------------------------------------------------------------------
       
   342 //
       
   343 void CUsbWatcher::DoCancel()
       
   344     {
       
   345     LOG_FUNC
       
   346 
       
   347     LOG1( "WatcherState = %d", iState );
       
   348     if( ( EUsbStarting == iState ) || ( EUsbStopping == iState ) )
       
   349         {
       
   350         iPersonalityHandler->Cancel();
       
   351 
       
   352         RProperty::Set( KPSUidUsbWatcher,
       
   353                 KUsbWatcherSelectedPersonality,
       
   354                 KUsbWatcherSelectedPersonalityNone );
       
   355         LOG( "personality set to none" );
       
   356 
       
   357         iState = EUsbIdle;
       
   358         }
       
   359     else if( EUsbConfirmStop == iState )
       
   360         {
       
   361         iPersonalityHandler->Cancel();
       
   362         iState = EUsbStarted;
       
   363         }
       
   364     else
       
   365         {
       
   366         LOG( "Nothingh to cancel" );
       
   367         }
       
   368     }
       
   369 
       
   370 // ----------------------------------------------------------------------------
       
   371 // This method implements state machine for personality start and stop.
       
   372 // ----------------------------------------------------------------------------
       
   373 //
       
   374 void CUsbWatcher::RunL()
       
   375     {
       
   376     LOG_FUNC
       
   377 
       
   378     LOG1( "WatcherState = %d", iState );
       
   379     TInt ret = iStatus.Int();
       
   380     if ( KErrNone != ret  )
       
   381         {
       
   382         LOG1( "ERROR: CUsbWatcher::RunL iStatus = %d", ret );
       
   383         }
       
   384 
       
   385     switch ( iState )
       
   386         {
       
   387         case EUsbStarting:
       
   388             LOG( "Personality started" );
       
   389             Notify( ret );
       
   390             if( iStopStartScenario )
       
   391                 {
       
   392                 iStopStartScenario = EFalse;
       
   393                 }
       
   394             //check if StartPersonality() fails     
       
   395             LEAVEIFERROR( ret );
       
   396             iState = EUsbStarted;
       
   397             break;
       
   398 
       
   399         case EUsbStopping:
       
   400             LOG( "Personality stopped" );
       
   401             iState = EUsbIdle;
       
   402             if( iStopStartScenario )
       
   403                 {
       
   404                 Start();
       
   405                 }
       
   406             else
       
   407                 {
       
   408                 RProperty::Set( KPSUidUsbWatcher,
       
   409                     KUsbWatcherSelectedPersonality,
       
   410                     KUsbWatcherSelectedPersonalityNone );
       
   411                 }
       
   412             break;
       
   413 
       
   414         case EUsbStarted:
       
   415             if( iStopStartScenario )
       
   416                 {
       
   417                 break;
       
   418                 }
       
   419 
       
   420             iPersonalityHandler->StopPersonality( iStatus );
       
   421             SetActive();
       
   422             iState = EUsbStopping;
       
   423             break;
       
   424 
       
   425         case EUsbIdle:
       
   426             if( iStopStartScenario )
       
   427                 {
       
   428                 Start();
       
   429                 }
       
   430             break;
       
   431 
       
   432         case EUsbConfirmStop:
       
   433             if( iStatus == KErrNone )
       
   434                 {
       
   435                 iStopStartScenario = ETrue;
       
   436                 iPersonalityHandler->StopPersonality( iStatus );
       
   437                 SetActive();
       
   438                 iState = EUsbStopping;
       
   439                 }
       
   440             else
       
   441                 {
       
   442                 Notify( ret );
       
   443                 iState = EUsbStarted;
       
   444                 }
       
   445             break;
       
   446 
       
   447         default:
       
   448             LOG( "ERROR: unexpected state" );
       
   449             PANIC( KErrGeneral );
       
   450             break;
       
   451         }
       
   452     }
       
   453 
       
   454 // ----------------------------------------------------------------------------
       
   455 // This method is not called cause RunL() never leaves.
       
   456 // ----------------------------------------------------------------------------
       
   457 //
       
   458 TInt CUsbWatcher::RunError(TInt aError)
       
   459     {
       
   460     LOG_FUNC
       
   461     
       
   462     LOG2("Returned error: %d, iState: %d", aError, iState);
       
   463     if ( iState == EUsbStarting )
       
   464         {
       
   465         RProperty::Set( KPSUidUsbWatcher,
       
   466                 KUsbWatcherSelectedPersonality,
       
   467                 KUsbWatcherSelectedPersonalityNone );
       
   468         LOG( "personality set to none" );
       
   469 
       
   470         iState = EUsbIdle;
       
   471         }
       
   472     
       
   473     return KErrNone;
       
   474     }
       
   475 
       
   476 // ----------------------------------------------------------------------------
       
   477 // Function is called when state of the device is locked.
       
   478 // ----------------------------------------------------------------------------
       
   479 //
       
   480 void CUsbWatcher::Lock()
       
   481     {
       
   482     LOG_FUNC
       
   483 
       
   484     if( IsDeviceA() ) // Not applicable in case of A-device
       
   485         {
       
   486         LOG( "Lock ignored in A-device state" );
       
   487         return;
       
   488         }
       
   489 
       
   490     
       
   491     TUsbDeviceState state = iActiveState->CurrentState();
       
   492 
       
   493     LOG1( "USB device state after lock: %d", state );
       
   494 
       
   495     if( EUsbDeviceStateUndefined != state ) // Stop personality
       
   496         {
       
   497         LOG( "Stopping USB persoanlity on device remote-lock" );
       
   498 
       
   499         iPersonalityHandler->CancelCableConnectedNotifier();
       
   500 
       
   501         if( iState != EUsbStarted )
       
   502             {
       
   503             Cancel();
       
   504             }
       
   505         else
       
   506             {
       
   507             Stop();
       
   508             }
       
   509         }
       
   510     }
       
   511 
       
   512 // ----------------------------------------------------------------------------
       
   513 // Function is called when state of the device is unlocked.
       
   514 // ----------------------------------------------------------------------------
       
   515 //
       
   516 void CUsbWatcher::Unlock()
       
   517     {
       
   518     LOG_FUNC
       
   519 
       
   520     if( IsDeviceA() ) // Not applicable in case of A-device
       
   521         {
       
   522         LOG( "Unlock ignored in A-device state" );
       
   523         return;
       
   524         }
       
   525 
       
   526     TUsbDeviceState state = iActiveState->CurrentState();
       
   527 
       
   528     LOG1( "USB device state after unlock: %d", state );
       
   529     if( EUsbDeviceStateAttached == state || EUsbDeviceStatePowered == state)
       
   530         {
       
   531         LOG( "Starting USB personality" );
       
   532         TInt err = iPersonalityRepository->Get(
       
   533            KUsbWatcherChangeOnConnectionSetting, iAskOnConnectionSetting );
       
   534         if( KErrNone == err )
       
   535             {
       
   536             Start();
       
   537             iAskOnConnectionSetting = KUsbWatcherChangeOnConnectionOff;
       
   538             }
       
   539         else
       
   540             {
       
   541             LOG1( "Error: CRepository::Get = %d", err );
       
   542             }
       
   543         }
       
   544     }
       
   545 
       
   546 // ----------------------------------------------------------------------------
       
   547 // This method is called when client wants to set new personality.
       
   548 // ----------------------------------------------------------------------------
       
   549 //
       
   550 void CUsbWatcher::SetPersonality( TInt aPersonalityId, TBool aNonBlocking )
       
   551     {
       
   552     LOG_FUNC
       
   553 
       
   554     LOG2( "aPersonalityId=%d, aNonBlocking=%d", aPersonalityId, aNonBlocking );
       
   555 
       
   556     // Check if personality is exist
       
   557     TBool found = EFalse;
       
   558 
       
   559     for( TInt i = 0; i < iSupportedPersonalities.Count(); i++ )
       
   560         {
       
   561         if( iSupportedPersonalities[i].iPersonalityId == aPersonalityId )
       
   562             {
       
   563             found = ETrue;
       
   564             }
       
   565         }
       
   566 
       
   567     if( !found )
       
   568         {
       
   569         Notify( KErrNotFound );
       
   570         return;
       
   571         }
       
   572 
       
   573     iSetPersonalityOngoing = ETrue;
       
   574     iPersonalityChangeOngoing = ETrue;
       
   575 
       
   576     //The previous personality is not changed, if the client wanted the
       
   577     //previous personality change to be temporary. The client has to call
       
   578     //SetPreviousPersonalityOnDisconnect after each SetPersonality to be
       
   579     //intended as temporary.
       
   580     if( iSetPreviousPersonalityOnDisconnect )
       
   581         {
       
   582         iSetPreviousPersonalityOnDisconnect = EFalse;
       
   583         }
       
   584     else
       
   585         {
       
   586         iOldPrevPersonalityId = iPrevPersonalityId;
       
   587         iPrevPersonalityId = iPersonalityId;
       
   588         LOG( "CUsbWatcher::SetPersonality setting previous" );
       
   589         }
       
   590     LOG1( " iPrevPersonalityId = %d", iPrevPersonalityId );
       
   591     if( iPersonalityId != aPersonalityId )
       
   592         {
       
   593         iPersonalityId = aPersonalityId;
       
   594         SwitchPersonality( aNonBlocking );
       
   595         }
       
   596     else
       
   597         {
       
   598         Notify( KErrNone );
       
   599         }
       
   600     }
       
   601 
       
   602 // ----------------------------------------------------------------------------
       
   603 // This method is called when client wants to cancel set personality.
       
   604 // ----------------------------------------------------------------------------
       
   605 //
       
   606 void CUsbWatcher::CancelSetPersonality()
       
   607     {
       
   608     LOG_FUNC
       
   609 
       
   610     Notify( KErrCancel );
       
   611     iPersonalityChangeOngoing = ETrue;
       
   612     iStopStartScenario = EFalse;
       
   613     SwitchPersonality();
       
   614     }
       
   615 
       
   616 // ----------------------------------------------------------------------------
       
   617 // This method is called when client wants to set previous personality.
       
   618 // ----------------------------------------------------------------------------
       
   619 //
       
   620 void CUsbWatcher::SetPreviousPersonality()
       
   621     {
       
   622     LOG_FUNC
       
   623 
       
   624     if( IsDeviceA() ) 
       
   625         {
       
   626         LOG( "SetPreviousPersonality not allowed in A-device state" );
       
   627         Notify( KErrAccessDenied );
       
   628         return;
       
   629         }
       
   630     
       
   631     TInt temp = iPersonalityId;
       
   632     iSetPreviousPersonalityOnDisconnect = EFalse;
       
   633 
       
   634     iPersonalityId = iPrevPersonalityId;
       
   635     iPrevPersonalityId = temp;
       
   636     iSetPreviousPersonalityOngoing = ETrue;
       
   637     iPersonalityChangeOngoing = ETrue;
       
   638 
       
   639     if( iPersonalityId != iPrevPersonalityId )
       
   640         {
       
   641         SwitchPersonality();
       
   642         }
       
   643     else
       
   644         {
       
   645         Notify( KErrNone );
       
   646         }
       
   647     }
       
   648 
       
   649 // ----------------------------------------------------------------------------
       
   650 // This method is called when client wants to cancel set previous personality.
       
   651 // ----------------------------------------------------------------------------
       
   652 //
       
   653 void CUsbWatcher::CancelSetPreviousPersonality()
       
   654     {
       
   655     LOG_FUNC
       
   656 
       
   657     Notify( KErrCancel );
       
   658     iPersonalityChangeOngoing = ETrue;
       
   659     iStopStartScenario = EFalse;
       
   660     SwitchPersonality();
       
   661     }
       
   662 
       
   663 // ----------------------------------------------------------------------------
       
   664 // This method is called when client wants to set previous personality on
       
   665 // disconnect.
       
   666 // ----------------------------------------------------------------------------
       
   667 //
       
   668 void CUsbWatcher::SetPreviousPersonalityOnDisconnect()
       
   669     {
       
   670     LOG_FUNC
       
   671 
       
   672     if( IsDeviceA() ) 
       
   673         {
       
   674         LOG( "Not allowed in A-device state" );
       
   675         Notify( KErrAccessDenied );
       
   676         return;
       
   677         }
       
   678 
       
   679     TUsbDeviceState state = iActiveState->CurrentState();
       
   680     LOG1( "Device state : %d", state );
       
   681     if( state != EUsbDeviceStateUndefined )
       
   682         {
       
   683         iSetPreviousPersonalityOnDisconnect = ETrue;
       
   684         }
       
   685     }
       
   686 
       
   687 // ----------------------------------------------------------------------------
       
   688 // This method starts personality change, if there is cable connected.
       
   689 // ----------------------------------------------------------------------------
       
   690 //
       
   691 void CUsbWatcher::SwitchPersonality( TBool aNonBlocking )
       
   692     {
       
   693     LOG_FUNC
       
   694 
       
   695 
       
   696     TUsbDeviceState state = iActiveState->CurrentState();
       
   697     LOG2( "IsDeviceA: %d, Device state : %d", IsDeviceA(), state );
       
   698 
       
   699     // As A-device, only cenrep will be updated for the reasons of
       
   700     // - In A-host state, device state will be undefined 
       
   701     // - In A-peripheral state, personality change can not happen otherwise 
       
   702     // the connection will be lost
       
   703     if ( IsDeviceA() || ( EUsbDeviceStateUndefined == state ) )
       
   704         {
       
   705         // if no connection -> just save the setting
       
   706         LOG( "CUsbWatcher::SwitchPersonality: Notify" );
       
   707         Notify( KErrNone );
       
   708         }
       
   709     else
       
   710         {
       
   711         switch ( iState )
       
   712             {
       
   713             case EUsbStopping:
       
   714             case EUsbStarting:
       
   715                 {
       
   716                 LOG( "CUsbWatcher::SwitchPersonality: Cancel & Start USB" );
       
   717                 Cancel();
       
   718                 Start();
       
   719                 }
       
   720                 break;
       
   721             case EUsbConfirmStop:
       
   722                 {
       
   723                 Cancel();
       
   724                 iState = EUsbStarted;
       
   725                 StopStart( aNonBlocking );
       
   726                 }
       
   727                 break;
       
   728             case EUsbStarted:
       
   729                 {
       
   730                 LOG( "CUsbWatcher::SwitchPersonality: Stop & Start USB" );
       
   731                 StopStart( aNonBlocking );
       
   732                 }
       
   733                 break;
       
   734             default:
       
   735                 {
       
   736                 LOG( "CUsbWatcher::SwitchPersonality: Start USB" );
       
   737                 Start();
       
   738                 }
       
   739                 break;
       
   740             }
       
   741         }
       
   742     }
       
   743 
       
   744 // ----------------------------------------------------------------------------
       
   745 // This method starts personality loading or continues stop start scenario.
       
   746 // ----------------------------------------------------------------------------
       
   747 //
       
   748 void CUsbWatcher::Start()
       
   749     {
       
   750     LOG_FUNC
       
   751 
       
   752     TInt globalState = CUsbGlobalSystemStateObserver::GlobalSystemState();
       
   753 
       
   754     if( iState == EUsbIdle )
       
   755         {
       
   756         iStarted = EFalse;
       
   757         iNormalStart = EFalse;
       
   758         if( globalState == ESwStateCharging )
       
   759             {
       
   760             LOG( "Global state: charging" );
       
   761             iGlobalStateObserver->Subscribe();
       
   762             iPrevPersonalityId=iPersonalityId;
       
   763             TInt ret = GetChargingPersonalityId( iPersonalityId );
       
   764             //do not start if charging personality not assigned
       
   765             if( KErrNone == ret )
       
   766                 {
       
   767                 RProperty::Set( KPSUidUsbWatcher,
       
   768                         KUsbWatcherSelectedPersonality, iPersonalityId );
       
   769                 iStarted = ETrue;
       
   770                 // Restore personality to normal in charging mode
       
   771                 iSetPreviousPersonalityOnDisconnect = ETrue;
       
   772                 iPersonalityHandler->StartPersonality( iPersonalityId,
       
   773                     KUsbWatcherChangeOnConnectionOff, iStatus );
       
   774                 }
       
   775             else
       
   776                 {
       
   777                 LOG1( "GetChargingPersonalityId = %d. Not started", ret );
       
   778                 }
       
   779             }
       
   780         else if( ( ( ESwStateNormalRfOn == globalState ) ||
       
   781                    ( ESwStateNormalRfOff == globalState ) ||
       
   782                    ( ESwStateNormalBTSap == globalState ) ))
       
   783             {
       
   784             LOG( "Global state: normal" );
       
   785             iNormalStart = ETrue;
       
   786             if( ! iUsbDeviceLock->Locked() )
       
   787                 {
       
   788                 iGlobalStateObserver->Cancel();
       
   789                 RProperty::Set( KPSUidUsbWatcher,
       
   790                             KUsbWatcherSelectedPersonality, iPersonalityId );
       
   791                 iStarted = ETrue;
       
   792                 iPersonalityHandler->StartPersonality( iPersonalityId,
       
   793                         iAskOnConnectionSetting, iStatus );
       
   794                 }
       
   795             else
       
   796                 {
       
   797                 LOG( "Device LOCKED, USB personality NOT start" );
       
   798                 }
       
   799             }
       
   800         else
       
   801             {
       
   802             LOG1( "Global state: = %d", globalState );
       
   803             //Cable connected in e.g. ChargingToNormal state and
       
   804             // personality started later in a normal state.
       
   805             iGlobalStateObserver->Subscribe();
       
   806             }
       
   807         if( iStarted )
       
   808             {
       
   809             SetActive();
       
   810             iState = EUsbStarting;
       
   811             }
       
   812         }
       
   813     else
       
   814         {
       
   815         LOG( "Tryign to call CUsbWatcher::Start in non-idle state " );
       
   816         PANIC( KErrGeneral );
       
   817         }
       
   818     }
       
   819 
       
   820 // ----------------------------------------------------------------------------
       
   821 // This method starts personality unloading or cancels personality start.
       
   822 // ----------------------------------------------------------------------------
       
   823 //
       
   824 void CUsbWatcher::Stop()
       
   825     {
       
   826     LOG_FUNC
       
   827 
       
   828     LOG1( "WatcherState = %d", iState );
       
   829     if( EUsbStarted == iState )
       
   830         {
       
   831         iPersonalityHandler->StopPersonality( iStatus );
       
   832         SetActive();
       
   833         iState = EUsbStopping;
       
   834         
       
   835         }
       
   836     else if( EUsbStarting  == iState )
       
   837         {
       
   838         LOG( "Cancel ongoing start." );
       
   839         Cancel();
       
   840         }
       
   841     
       
   842     else
       
   843         {
       
   844         LOG( "Wrong state for Stop" );
       
   845         }
       
   846     }
       
   847 
       
   848 // ----------------------------------------------------------------------------
       
   849 // This method is used when there is need to change currently loaded
       
   850 // personality.
       
   851 // ----------------------------------------------------------------------------
       
   852 //
       
   853 void CUsbWatcher::StopStart( TBool aNonBlocking )
       
   854     {
       
   855     LOG_FUNC
       
   856 
       
   857     LOG1( "WatcherState = %d", iState );
       
   858     if( iState == EUsbStarted )
       
   859         {
       
   860         iState = EUsbConfirmStop;
       
   861         if( !aNonBlocking )
       
   862             {
       
   863             iPersonalityHandler->ConfirmPersonalityUnload( iStatus );
       
   864             SetActive();
       
   865             }
       
   866         else
       
   867             {
       
   868             LOG( "CUsbWatcher::StopStart not confirming" );
       
   869             SetActive();
       
   870             TRequestStatus* status = &iStatus;
       
   871             User::RequestComplete( status, KErrNone );
       
   872             }
       
   873         }
       
   874     else
       
   875         {
       
   876         LOG( "Wrong state to StopStart" );
       
   877         }
       
   878     }
       
   879 
       
   880 // ----------------------------------------------------------------------------
       
   881 // CUsbWatcherSession uses this method to register observer.
       
   882 // ----------------------------------------------------------------------------
       
   883 //
       
   884 void CUsbWatcher::RegisterObserverL( MUsbWatcherNotify* aObserver )
       
   885     {
       
   886     LOG_FUNC
       
   887 
       
   888     TInt index = iObservers.Find( aObserver );
       
   889     if( index < 0 )
       
   890         {
       
   891         iObservers.AppendL( aObserver );
       
   892         }
       
   893     }
       
   894 
       
   895 // ----------------------------------------------------------------------------
       
   896 // CUsbWatcherSession uses this method to deregister observer.
       
   897 // ----------------------------------------------------------------------------
       
   898 //
       
   899 void CUsbWatcher::DeRegisterObserver( MUsbWatcherNotify* aObserver )
       
   900     {
       
   901     LOG_FUNC
       
   902 
       
   903     TInt index = iObservers.Find( aObserver );
       
   904 
       
   905     if( index >= 0 )
       
   906         {
       
   907         iObservers.Remove( index );
       
   908         }
       
   909     }
       
   910 
       
   911 // ----------------------------------------------------------------------------
       
   912 // This method is used to complete any outstanding request.
       
   913 // ----------------------------------------------------------------------------
       
   914 //
       
   915 void CUsbWatcher::Notify( TInt aStatus )
       
   916     {
       
   917     LOG_FUNC
       
   918 
       
   919     LOG1( "aStatus = %d", aStatus );
       
   920     TInt status = aStatus;
       
   921 
       
   922     // clear every time when notified
       
   923     iPersonalityChangeOngoing = EFalse;
       
   924 
       
   925     if( iSetPersonalityOngoing || iChangePersonalityOngoing )
       
   926         {
       
   927         iSetPersonalityOngoing = EFalse;
       
   928         iChangePersonalityOngoing = EFalse;
       
   929 
       
   930         if( status == KErrNone )
       
   931             {
       
   932             status = WritePersonalityId( iPersonalityId );
       
   933             }
       
   934         else
       
   935             {
       
   936             // in case of error return to state before SetPersonality
       
   937             iPersonalityId = iPrevPersonalityId;
       
   938             iPrevPersonalityId = iOldPrevPersonalityId;
       
   939             }
       
   940         }
       
   941 
       
   942     if( iSetPreviousPersonalityOngoing )
       
   943         {
       
   944         iSetPreviousPersonalityOngoing = EFalse;
       
   945 
       
   946         if( status == KErrNone )
       
   947             {
       
   948             WritePersonalityId( iPersonalityId );
       
   949             }
       
   950         else
       
   951             {
       
   952             // in case of error return to state before SetPreviousPersonality
       
   953             TInt temp = iPrevPersonalityId;
       
   954 
       
   955             iPrevPersonalityId = iPersonalityId;
       
   956             iPersonalityId = temp;
       
   957             }
       
   958         }
       
   959 
       
   960     for( TInt i = 0; i < iObservers.Count(); i++ )
       
   961         {
       
   962         iObservers[i]->Notify( iPersonalityId, status );
       
   963         }
       
   964     }
       
   965 
       
   966 // ----------------------------------------------------------------------------
       
   967 // Stop loaded personality. Called from global state handler
       
   968 // ----------------------------------------------------------------------------
       
   969 //
       
   970 void CUsbWatcher::StopPersonality()
       
   971     {
       
   972     LOG_FUNC
       
   973     // restore settings
       
   974     iPersonalityId = iPrevPersonalityId;
       
   975 
       
   976     Stop();
       
   977     iStarted = EFalse;
       
   978     }
       
   979 
       
   980 // ----------------------------------------------------------------------------
       
   981 // Start personality. Called from global state handler
       
   982 // ----------------------------------------------------------------------------
       
   983 //
       
   984 void CUsbWatcher::StartPersonality()
       
   985     {
       
   986     LOG_FUNC
       
   987 
       
   988     if( !iStarted )
       
   989         {
       
   990         Start();
       
   991         }
       
   992 
       
   993     //start usbdevcon only in normal global state
       
   994     TInt globalState = CUsbGlobalSystemStateObserver::GlobalSystemState();
       
   995     if( ( globalState == ESwStateNormalRfOn ) ||
       
   996             ( globalState == ESwStateNormalRfOff ) ||
       
   997             ( globalState == ESwStateNormalBTSap ) )
       
   998         {
       
   999         iUsbDevConStarter->Start();
       
  1000         }
       
  1001     }
       
  1002 
       
  1003 // ----------------------------------------------------------------------------
       
  1004 // Read default personality from ini file. Used in charging mode
       
  1005 // ----------------------------------------------------------------------------
       
  1006 //
       
  1007 TInt CUsbWatcher::GetChargingPersonalityId( TInt& aPersonalityId )
       
  1008     {
       
  1009     LOG_FUNC
       
  1010 
       
  1011     TInt ret = iPersonalityRepository->Get(
       
  1012             KUsbWatcherChargingDefaultPersonality, aPersonalityId );
       
  1013     return ret;
       
  1014     }
       
  1015 
       
  1016 // ----------------------------------------------------------------------------
       
  1017 // Check if there is an observer with ask on connection suppression
       
  1018 // ----------------------------------------------------------------------------
       
  1019 //
       
  1020 TBool CUsbWatcher::IsAskOnConnectionSuppression()
       
  1021     {
       
  1022     LOG_FUNC
       
  1023     
       
  1024     TBool ret( EFalse );
       
  1025     for( TInt i = 0; i < iObservers.Count(); i++ )
       
  1026         {
       
  1027         if( iObservers[i]->IsAskOnConnectionSuppressed() )
       
  1028             {
       
  1029             ret = ETrue;
       
  1030             break;
       
  1031             }
       
  1032         }
       
  1033     LOG1( "Return = %d", ret );
       
  1034     return ret;
       
  1035     }
       
  1036 
       
  1037 // ----------------------------------------------------------------------------
       
  1038 // Check current A or B device state
       
  1039 // ----------------------------------------------------------------------------
       
  1040 //
       
  1041 TBool CUsbWatcher::IsDeviceA()
       
  1042     {
       
  1043     //NOT LOGGED
       
  1044     // return EFalse in non-OTG configuration otherwise ask UsbOtgWatcher
       
  1045     return iOtgWatcher ? iOtgWatcher->IsDeviceA() : EFalse;
       
  1046     }
       
  1047 
       
  1048 // ----------------------------------------------------------------------------
       
  1049 // Write new personality to central repository.
       
  1050 // ----------------------------------------------------------------------------
       
  1051 //
       
  1052 TInt CUsbWatcher::WritePersonalityId( TInt aPersonalityId )
       
  1053     {
       
  1054     LOG_FUNC
       
  1055     
       
  1056     // Save as the default personality only if it is not hidden
       
  1057     TUint32 property(0);
       
  1058     TInt ret =  iUsbMan.GetPersonalityProperty( aPersonalityId, property );
       
  1059     if ( ret == KErrNone )
       
  1060         {
       
  1061         LOG2( "Personality %d property: 0x%x", aPersonalityId, property );
       
  1062         }
       
  1063     else
       
  1064         {
       
  1065         //Not fatal, treat as non-hidden
       
  1066         LOG1( "ERROR: GetPersonalityProperty = %d", ret );
       
  1067         property = 0;
       
  1068         }
       
  1069     if ( property & KUsbPersonalityPropertyHidden ) //Bitwise AND
       
  1070         {
       
  1071         LOG( "Hidden personality not saved to central repository" );
       
  1072         ret = KErrNone;
       
  1073         }
       
  1074     else
       
  1075         {
       
  1076         ret =  iPersonalityRepository->Set( KUsbWatcherPersonality,
       
  1077             aPersonalityId );
       
  1078         }
       
  1079     return ret;
       
  1080     }
       
  1081 
       
  1082 // End of file