keepalive/flextimer/client/src/rflextimer.cpp
changeset 32 5c4486441ae6
equal deleted inserted replaced
31:c16e04725da3 32:5c4486441ae6
       
     1 /*
       
     2  * Copyright (c) 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:  Implementation of RFlexTimer class
       
    15  *
       
    16  */
       
    17 
       
    18 /*
       
    19  * %version: 1 %
       
    20  */
       
    21 #include "rflextimer.h"
       
    22 #include "flextimercommon.h"
       
    23 #include "OstTraceDefinitions.h"
       
    24 #ifdef OST_TRACE_COMPILER_IN_USE
       
    25 #include "rflextimerTraces.h"
       
    26 #endif
       
    27 
       
    28 
       
    29 _LIT( KFlexTimerSemaphoreName, "FlexTimerSemaphore" );
       
    30 
       
    31 // Semaphore count value initialization to 1. The 1st to call Wait() will
       
    32 // pass the semaphore. Other processes attempting entry will wait until the
       
    33 // 1st one has called Signal() on the semaphore.
       
    34 const TInt KPassFirstWaitEntry = 1;
       
    35 
       
    36 // ======== MEMBER FUNCTIONS ========
       
    37 // ---------------------------------------------------------------------------
       
    38 // Constructs the object.
       
    39 // ---------------------------------------------------------------------------
       
    40 //
       
    41 EXPORT_C RFlexTimer::RFlexTimer()
       
    42     {
       
    43     OstTrace1( TRACE_NORMAL, RFLEXTIMER_RFLEXTIMER,
       
    44                "RFlexTimer::RFlexTimer;this=%x", this );
       
    45     
       
    46     }
       
    47 
       
    48 // ---------------------------------------------------------------------------
       
    49 // Destructs the object.
       
    50 // ---------------------------------------------------------------------------
       
    51 //
       
    52 EXPORT_C RFlexTimer::~RFlexTimer()
       
    53     {
       
    54     OstTrace1( TRACE_NORMAL, DUP1_RFLEXTIMER_RFLEXTIMER,
       
    55                "RFlexTimer::~RFlexTimer;this=%x", ( TUint )this );
       
    56     
       
    57     Close();
       
    58     }
       
    59 
       
    60 // ---------------------------------------------------------------------------
       
    61 // Connects to the server and create a session.
       
    62 // ---------------------------------------------------------------------------
       
    63 //
       
    64 EXPORT_C TInt RFlexTimer::Connect()
       
    65     {
       
    66     OstTrace1( TRACE_NORMAL, RFLEXTIMER_CONNECT,
       
    67                "RFlexTimer::Connect;this=%x", ( TUint )this );
       
    68     
       
    69     // Not opened handle-number
       
    70     const TInt kHandleNotOpened( 0 );
       
    71     
       
    72     // Starts the server, if it does not already exist in the system.
       
    73     TInt ret = StartServer();
       
    74 
       
    75     if ( ret == KErrNone )
       
    76         { // No session, create it
       
    77 
       
    78         // Handle() is zero when initialized RHandleBase. Close() also zeroes 
       
    79         // the handle. If CreateSession() fails, Handle() is still zero.
       
    80         // If session is created ok, the Handle() contains the (non zero)
       
    81         // handle-number. 
       
    82         //
       
    83         // Handle() can be used for checking is the handle opened or not.
       
    84         //
       
    85         if ( Handle() == kHandleNotOpened )
       
    86             {
       
    87             // Creates the session for this client.
       
    88             ret = CreateSession( KFlexTimerServerName,
       
    89                                  Version(),
       
    90                                  KFlexTimerServerMessageSlots );
       
    91             }
       
    92         else
       
    93             { // Session already exists - panic.
       
    94 
       
    95             OstTrace1( 
       
    96                 TRACE_NORMAL, 
       
    97                 DUP1_RFLEXTIMER_CONNECT,
       
    98                 "RFlexTimer::Connect already connected - PANIC;this=%x", 
       
    99                 ( TUint )this );
       
   100         
       
   101             User::Panic( KRFlexTimerPanicCat, EFlexTimerAlreadyConnected );
       
   102             }
       
   103         }
       
   104     return ret;
       
   105     }
       
   106 
       
   107 // ---------------------------------------------------------------------------
       
   108 // Cancels any outstanding request to the server.
       
   109 // ---------------------------------------------------------------------------
       
   110 //
       
   111 EXPORT_C void RFlexTimer::Cancel()
       
   112     {
       
   113     OstTrace1( TRACE_NORMAL, RFLEXTIMER_CANCEL,
       
   114                "RFlexTimer::Cancel;this=%x", ( TUint )this );
       
   115     
       
   116     SendReceive( EFlexTimerServCancelRequest );
       
   117     }
       
   118 
       
   119 // ---------------------------------------------------------------------------
       
   120 // Fire timer at latest on the given interval. 32-bit interval.
       
   121 // ---------------------------------------------------------------------------
       
   122 //
       
   123 EXPORT_C void RFlexTimer::After( TRequestStatus& aStatus,
       
   124                                  TTimeIntervalMicroSeconds32 aInterval )
       
   125     {
       
   126     OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AFTER32,
       
   127                   "RFlexTimer::After32;this=%x;aStatus=%x;aInterval=%d",
       
   128                   ( TUint )this, ( TUint )&( aStatus ), aInterval.Int() );
       
   129     
       
   130     const TTimeIntervalMicroSeconds32 ZERO_INTERVAL32(0);
       
   131     __ASSERT_ALWAYS(aInterval >= ZERO_INTERVAL32,
       
   132                     User::Panic(KRFlexTimerPanicCat,
       
   133                                 EFlexTimerAfterIntervalLessThanZero));
       
   134     
       
   135     TIpcArgs args( aInterval.Int(), 0 );
       
   136     //asynchronous request for timer creation and timeout request.    
       
   137     SendReceive( EFlexTimerServAfterRequest, args, aStatus );
       
   138     }
       
   139 
       
   140 // ---------------------------------------------------------------------------
       
   141 // Fire timer at latest on the given interval. 64-bit interval.
       
   142 // ---------------------------------------------------------------------------
       
   143 //
       
   144 EXPORT_C void RFlexTimer::After( TRequestStatus& aStatus,
       
   145                                  TTimeIntervalMicroSeconds aInterval )
       
   146     {
       
   147     OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AFTER64,
       
   148                   "RFlexTimer::After64;this=%x;aStatus=%x;aInterval=%lld",
       
   149                   ( TUint )this, ( TUint )&( aStatus ), aInterval.Int64() );
       
   150     
       
   151     const TTimeIntervalMicroSeconds ZERO_INTERVAL(0);
       
   152     __ASSERT_ALWAYS(aInterval >= ZERO_INTERVAL,
       
   153                     User::Panic(KRFlexTimerPanicCat,
       
   154                                 EFlexTimerAfterIntervalLessThanZero));
       
   155     
       
   156     TIpcArgs args( I64LOW(aInterval.Int64()), I64HIGH(aInterval.Int64()) );
       
   157     //asynchronous request for timer creation and timeout request.    
       
   158     SendReceive( EFlexTimerServAfterRequest, args, aStatus );
       
   159     }
       
   160 
       
   161 // ---------------------------------------------------------------------------
       
   162 // Fire timer at latest after the given number of ticks.
       
   163 // ---------------------------------------------------------------------------
       
   164 //
       
   165 EXPORT_C void RFlexTimer::AfterTicks( TRequestStatus& aStatus, TInt aTicks )
       
   166     {
       
   167     OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AFTERTICKS,
       
   168                   "RFlexTimer::AfterTicks;this=%x;aStatus=%d;aTicks=%d",
       
   169                   ( TUint )this, ( TUint )&( aStatus ), aTicks );
       
   170     
       
   171     __ASSERT_ALWAYS(aTicks >= 0,
       
   172                     User::Panic(KRFlexTimerPanicCat,
       
   173                                 EFlexTimerAfterTicksIntervalLessThanZero));
       
   174 
       
   175     TIpcArgs args( aTicks );
       
   176     //asynchronous request for timer creation and timeout request.    
       
   177     SendReceive( EFlexTimerServAfterTicksRequest, args, aStatus );
       
   178     }
       
   179 
       
   180 // ---------------------------------------------------------------------------
       
   181 // Fire timer between at latest by the given time value.
       
   182 // ---------------------------------------------------------------------------
       
   183 //
       
   184 EXPORT_C void RFlexTimer::At( TRequestStatus& aStatus, const TTime& aTime )
       
   185     {
       
   186     OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AT,
       
   187                   "RFlexTimer::At;this=%x;aStatus=%d;aTime=%lld",
       
   188                   ( TUint )this, ( TUint )&( aStatus ), aTime.Int64() );
       
   189     
       
   190     TTime nowTime;
       
   191     nowTime.HomeTime();
       
   192     
       
   193     __ASSERT_ALWAYS(aTime >= nowTime,
       
   194                     User::Panic(KRFlexTimerPanicCat,
       
   195                                 EFlexTimerAtIntervalLessThanZero));
       
   196     
       
   197     TIpcArgs args( I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()) );
       
   198     //asynchronous request for timer creation and timeout request.    
       
   199     SendReceive( EFlexTimerServAtRequest, args, aStatus );
       
   200     }
       
   201 
       
   202 // ---------------------------------------------------------------------------
       
   203 // Fire timer between at latest by the given time value.
       
   204 // ---------------------------------------------------------------------------
       
   205 //
       
   206 EXPORT_C void RFlexTimer::AtUTC( TRequestStatus& aStatus, const TTime& aTime )
       
   207     {
       
   208     OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_ATUTC,
       
   209                   "RFlexTimer::AtUTC;this=%x;aStatus=%d;aTime=%lld",
       
   210                   ( TUint )this, ( TUint )&( aStatus ), aTime.Int64() );
       
   211     
       
   212     TTime nowTime;
       
   213     nowTime.UniversalTime();
       
   214     
       
   215     __ASSERT_ALWAYS(aTime >= nowTime,
       
   216                     User::Panic(KRFlexTimerPanicCat,
       
   217                                 EFlexTimerAtUTCIntervalLessThanZero));
       
   218     
       
   219     TIpcArgs args( I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()) );
       
   220     //asynchronous request for timer creation and timeout request.    
       
   221     SendReceive( EFlexTimerServAtUTCRequest, args, aStatus );
       
   222     }
       
   223 
       
   224 // ---------------------------------------------------------------------------
       
   225 // Sets the window size in which alignment is possible for the timer.
       
   226 // This is a synchronous command. 32-bit function version.
       
   227 // ---------------------------------------------------------------------------
       
   228 //
       
   229 EXPORT_C TInt RFlexTimer::Configure( TTimeIntervalMicroSeconds32 aWindowSize )
       
   230     {
       
   231     OstTraceExt2( TRACE_NORMAL, RFLEXTIMER_CONFIGURE,
       
   232                   "RFlexTimer::Configure32;this=%x;aWindowSize=%d",
       
   233                   ( TUint )this, aWindowSize.Int() );
       
   234     
       
   235     const TTimeIntervalMicroSeconds32 ZERO_INTERVAL32(0);
       
   236     __ASSERT_ALWAYS(aWindowSize >= ZERO_INTERVAL32,
       
   237                     User::Panic(KRFlexTimerPanicCat,
       
   238                                 EFlexTimerWindowLessThanZero));
       
   239     
       
   240     TInt64 transfer = MAKE_TINT64( 0, aWindowSize.Int() );
       
   241         
       
   242     // Regardless of the user function, the window size is always transmitted
       
   243     // as a 64-bit integer.
       
   244     TIpcArgs args( EConfigureRequestWindowSize, 
       
   245                    I64LOW(transfer), I64HIGH(transfer) );
       
   246 
       
   247     return SendReceive( EFlexTimerServConfigureRequest, args );
       
   248     }
       
   249 
       
   250 // ---------------------------------------------------------------------------
       
   251 // Sets the window size in which alignment is possible for the timer.
       
   252 // This is a synchronous command. 64-bit function version.
       
   253 // ---------------------------------------------------------------------------
       
   254 //
       
   255 EXPORT_C TInt RFlexTimer::Configure( TTimeIntervalMicroSeconds aWindowSize )
       
   256     {
       
   257     OstTraceExt2( TRACE_NORMAL, DUP1_RFLEXTIMER_CONFIGURE,
       
   258                   "RFlexTimer::Configure64;this=%x;aWindowSize=%lld",
       
   259                   ( TUint )this, aWindowSize.Int64() );
       
   260     
       
   261     const TTimeIntervalMicroSeconds ZERO_INTERVAL64(0);
       
   262     __ASSERT_ALWAYS(aWindowSize >= ZERO_INTERVAL64,
       
   263                     User::Panic(KRFlexTimerPanicCat,
       
   264                                 EFlexTimerWindowLessThanZero));
       
   265     
       
   266     // Regardless of the user function, the window size is always transmitted
       
   267     // as a 64-bit integer.
       
   268     TIpcArgs args( EConfigureRequestWindowSize,
       
   269                    I64LOW(aWindowSize.Int64()),
       
   270                    I64HIGH(aWindowSize.Int64()) );
       
   271 
       
   272     return SendReceive( EFlexTimerServConfigureRequest, args  );
       
   273     }
       
   274 
       
   275 // ---------------------------------------------------------------------------
       
   276 // Gets the version number.
       
   277 // ---------------------------------------------------------------------------
       
   278 //
       
   279 TVersion RFlexTimer::Version() const
       
   280     {
       
   281     return ( TVersion( KFlexTimerServMajorVersionNumber,
       
   282                        KFlexTimerServMinorVersionNumber,
       
   283                        KFlexTimerServBuildVersionNumber ) );
       
   284     }
       
   285 
       
   286 // ---------------------------------------------------------------------------
       
   287 // Connects to the server. If server does not exist, it is created.
       
   288 // ---------------------------------------------------------------------------
       
   289 //
       
   290 TInt RFlexTimer::StartServer()
       
   291     {
       
   292     OstTrace1( TRACE_NORMAL, RFLEXTIMER_STARTSERVER,
       
   293                "RFlexTimer::StartServer;this=%x", ( TUint )this );
       
   294     
       
   295     TFindServer findServer( KFlexTimerServerName );
       
   296     TFullName serverName;
       
   297 
       
   298     // See if the server is already started. 
       
   299     TInt ret = findServer.Next( serverName );
       
   300     
       
   301     if ( ret != KErrNone )
       
   302         {
       
   303         //Server was not found so create one.
       
   304         RProcess serverProcess;
       
   305         TBuf<1> serverParameters;
       
   306 
       
   307         // Semaphore to guard the opening of the server process.
       
   308         RSemaphore semaphore;
       
   309 
       
   310         // Prevent two clients from  creating the serverProcess at the same
       
   311         // time.
       
   312         if ( ( ret = semaphore.CreateGlobal( 
       
   313                 KFlexTimerSemaphoreName, KPassFirstWaitEntry ) ) != KErrNone )
       
   314             {
       
   315             ret = semaphore.OpenGlobal( KFlexTimerSemaphoreName );
       
   316             }
       
   317 
       
   318         if ( ret == KErrNone )
       
   319             {
       
   320             semaphore.Wait();
       
   321 
       
   322             // See again if the server is already started. This doublechecking
       
   323             // is necessary, since two or processes may have resolved the
       
   324             // first findserver before any server was created.
       
   325 
       
   326             // TFindServer sets its content only when instantiated.
       
   327             // Just using findServer.Next() does not work in here.
       
   328             TFindServer findServerAgain( KFlexTimerServerName );
       
   329             if ( findServerAgain.Next( serverName ) != KErrNone )
       
   330                 {
       
   331                 // Load the executable for the server.
       
   332                 ret = serverProcess.Create( KFlexTimerServerExe,
       
   333                                             serverParameters,
       
   334                                             EOwnerThread );
       
   335 
       
   336                 if ( ret == KErrNone )
       
   337                     {
       
   338                     // Server has been created successfully. It is initially 
       
   339                     // in suspended state. Now resume the server process.
       
   340                     serverProcess.Resume();
       
   341 
       
   342                     // Wait until the server process has been started.
       
   343                     TRequestStatus status;
       
   344                     serverProcess.Rendezvous( status );
       
   345                     User::WaitForRequest( status );
       
   346 
       
   347                     // Check if server has panicked during initialization.
       
   348                     ret = serverProcess.ExitType();
       
   349                     if ( ret == EExitPanic )
       
   350                         {
       
   351                         OstTrace1( TRACE_NORMAL, DUP1_RFLEXTIMER_STARTSERVER,
       
   352                                 "RFlexTimer::StartServer;this=%x; "
       
   353                                 "ERROR: Server paniced",
       
   354                                 ( TUint )this );
       
   355 
       
   356                         ret = KErrServerTerminated;
       
   357                         }
       
   358                     else
       
   359                         {
       
   360                         ret = status.Int();
       
   361                         }
       
   362 
       
   363                     // The server process stands on its own. This handle can
       
   364                     // be closed. 
       
   365                     serverProcess.Close();
       
   366                     }
       
   367                 else
       
   368                     {
       
   369                     OstTrace1( TRACE_NORMAL, DUP2_RFLEXTIMER_STARTSERVER,
       
   370                             "RFlexTimer::StartServer;this=%x; "
       
   371                             "ERROR: Server creation failed",
       
   372                             ( TUint )this );
       
   373                     }
       
   374                 }
       
   375             
       
   376             semaphore.Signal();
       
   377             semaphore.Close();
       
   378             }
       
   379         }
       
   380 
       
   381     return ret;
       
   382     }
       
   383