keepalive/flextimer/client/src/rflextimer.cpp
branchRCL_3
changeset 57 05bc53fe583b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keepalive/flextimer/client/src/rflextimer.cpp	Tue Aug 31 15:35:44 2010 +0300
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 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:  Implementation of RFlexTimer class
+ *
+ */
+
+/*
+ * %version: 1 %
+ */
+#include "rflextimer.h"
+#include "flextimercommon.h"
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "rflextimerTraces.h"
+#endif
+
+
+_LIT( KFlexTimerSemaphoreName, "FlexTimerSemaphore" );
+
+// Semaphore count value initialization to 1. The 1st to call Wait() will
+// pass the semaphore. Other processes attempting entry will wait until the
+// 1st one has called Signal() on the semaphore.
+const TInt KPassFirstWaitEntry = 1;
+
+// ======== MEMBER FUNCTIONS ========
+// ---------------------------------------------------------------------------
+// Constructs the object.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C RFlexTimer::RFlexTimer()
+    {
+    OstTrace1( TRACE_NORMAL, RFLEXTIMER_RFLEXTIMER,
+               "RFlexTimer::RFlexTimer;this=%x", this );
+    
+    }
+
+// ---------------------------------------------------------------------------
+// Destructs the object.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C RFlexTimer::~RFlexTimer()
+    {
+    OstTrace1( TRACE_NORMAL, DUP1_RFLEXTIMER_RFLEXTIMER,
+               "RFlexTimer::~RFlexTimer;this=%x", ( TUint )this );
+    
+    Close();
+    }
+
+// ---------------------------------------------------------------------------
+// Connects to the server and create a session.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt RFlexTimer::Connect()
+    {
+    OstTrace1( TRACE_NORMAL, RFLEXTIMER_CONNECT,
+               "RFlexTimer::Connect;this=%x", ( TUint )this );
+    
+    // Not opened handle-number
+    const TInt kHandleNotOpened( 0 );
+    
+    // Starts the server, if it does not already exist in the system.
+    TInt ret = StartServer();
+
+    if ( ret == KErrNone )
+        { // No session, create it
+
+        // Handle() is zero when initialized RHandleBase. Close() also zeroes 
+        // the handle. If CreateSession() fails, Handle() is still zero.
+        // If session is created ok, the Handle() contains the (non zero)
+        // handle-number. 
+        //
+        // Handle() can be used for checking is the handle opened or not.
+        //
+        if ( Handle() == kHandleNotOpened )
+            {
+            // Creates the session for this client.
+            ret = CreateSession( KFlexTimerServerName,
+                                 Version(),
+                                 KFlexTimerServerMessageSlots );
+            }
+        else
+            { // Session already exists - panic.
+
+            OstTrace1( 
+                TRACE_NORMAL, 
+                DUP1_RFLEXTIMER_CONNECT,
+                "RFlexTimer::Connect already connected - PANIC;this=%x", 
+                ( TUint )this );
+        
+            User::Panic( KRFlexTimerPanicCat, EFlexTimerAlreadyConnected );
+            }
+        }
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// Cancels any outstanding request to the server.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void RFlexTimer::Cancel()
+    {
+    OstTrace1( TRACE_NORMAL, RFLEXTIMER_CANCEL,
+               "RFlexTimer::Cancel;this=%x", ( TUint )this );
+    
+    SendReceive( EFlexTimerServCancelRequest );
+    }
+
+// ---------------------------------------------------------------------------
+// Fire timer at latest on the given interval. 32-bit interval.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void RFlexTimer::After( TRequestStatus& aStatus,
+                                 TTimeIntervalMicroSeconds32 aInterval )
+    {
+    OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AFTER32,
+                  "RFlexTimer::After32;this=%x;aStatus=%x;aInterval=%d",
+                  ( TUint )this, ( TUint )&( aStatus ), aInterval.Int() );
+    
+    const TTimeIntervalMicroSeconds32 ZERO_INTERVAL32(0);
+    __ASSERT_ALWAYS(aInterval >= ZERO_INTERVAL32,
+                    User::Panic(KRFlexTimerPanicCat,
+                                EFlexTimerAfterIntervalLessThanZero));
+    
+    TIpcArgs args( aInterval.Int(), 0 );
+    //asynchronous request for timer creation and timeout request.    
+    SendReceive( EFlexTimerServAfterRequest, args, aStatus );
+    }
+
+// ---------------------------------------------------------------------------
+// Fire timer at latest on the given interval. 64-bit interval.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void RFlexTimer::After( TRequestStatus& aStatus,
+                                 TTimeIntervalMicroSeconds aInterval )
+    {
+    OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AFTER64,
+                  "RFlexTimer::After64;this=%x;aStatus=%x;aInterval=%lld",
+                  ( TUint )this, ( TUint )&( aStatus ), aInterval.Int64() );
+    
+    const TTimeIntervalMicroSeconds ZERO_INTERVAL(0);
+    __ASSERT_ALWAYS(aInterval >= ZERO_INTERVAL,
+                    User::Panic(KRFlexTimerPanicCat,
+                                EFlexTimerAfterIntervalLessThanZero));
+    
+    TIpcArgs args( I64LOW(aInterval.Int64()), I64HIGH(aInterval.Int64()) );
+    //asynchronous request for timer creation and timeout request.    
+    SendReceive( EFlexTimerServAfterRequest, args, aStatus );
+    }
+
+// ---------------------------------------------------------------------------
+// Fire timer at latest after the given number of ticks.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void RFlexTimer::AfterTicks( TRequestStatus& aStatus, TInt aTicks )
+    {
+    OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AFTERTICKS,
+                  "RFlexTimer::AfterTicks;this=%x;aStatus=%d;aTicks=%d",
+                  ( TUint )this, ( TUint )&( aStatus ), aTicks );
+    
+    __ASSERT_ALWAYS(aTicks >= 0,
+                    User::Panic(KRFlexTimerPanicCat,
+                                EFlexTimerAfterTicksIntervalLessThanZero));
+
+    TIpcArgs args( aTicks );
+    //asynchronous request for timer creation and timeout request.    
+    SendReceive( EFlexTimerServAfterTicksRequest, args, aStatus );
+    }
+
+// ---------------------------------------------------------------------------
+// Fire timer between at latest by the given time value.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void RFlexTimer::At( TRequestStatus& aStatus, const TTime& aTime )
+    {
+    OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AT,
+                  "RFlexTimer::At;this=%x;aStatus=%d;aTime=%lld",
+                  ( TUint )this, ( TUint )&( aStatus ), aTime.Int64() );
+    
+    TTime nowTime;
+    nowTime.HomeTime();
+    
+    __ASSERT_ALWAYS(aTime >= nowTime,
+                    User::Panic(KRFlexTimerPanicCat,
+                                EFlexTimerAtIntervalLessThanZero));
+    
+    TIpcArgs args( I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()) );
+    //asynchronous request for timer creation and timeout request.    
+    SendReceive( EFlexTimerServAtRequest, args, aStatus );
+    }
+
+// ---------------------------------------------------------------------------
+// Fire timer between at latest by the given time value.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void RFlexTimer::AtUTC( TRequestStatus& aStatus, const TTime& aTime )
+    {
+    OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_ATUTC,
+                  "RFlexTimer::AtUTC;this=%x;aStatus=%d;aTime=%lld",
+                  ( TUint )this, ( TUint )&( aStatus ), aTime.Int64() );
+    
+    TTime nowTime;
+    nowTime.UniversalTime();
+    
+    __ASSERT_ALWAYS(aTime >= nowTime,
+                    User::Panic(KRFlexTimerPanicCat,
+                                EFlexTimerAtUTCIntervalLessThanZero));
+    
+    TIpcArgs args( I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()) );
+    //asynchronous request for timer creation and timeout request.    
+    SendReceive( EFlexTimerServAtUTCRequest, args, aStatus );
+    }
+
+// ---------------------------------------------------------------------------
+// Sets the window size in which alignment is possible for the timer.
+// This is a synchronous command. 32-bit function version.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt RFlexTimer::Configure( TTimeIntervalMicroSeconds32 aWindowSize )
+    {
+    OstTraceExt2( TRACE_NORMAL, RFLEXTIMER_CONFIGURE,
+                  "RFlexTimer::Configure32;this=%x;aWindowSize=%d",
+                  ( TUint )this, aWindowSize.Int() );
+    
+    const TTimeIntervalMicroSeconds32 ZERO_INTERVAL32(0);
+    __ASSERT_ALWAYS(aWindowSize >= ZERO_INTERVAL32,
+                    User::Panic(KRFlexTimerPanicCat,
+                                EFlexTimerWindowLessThanZero));
+    
+    TInt64 transfer = MAKE_TINT64( 0, aWindowSize.Int() );
+        
+    // Regardless of the user function, the window size is always transmitted
+    // as a 64-bit integer.
+    TIpcArgs args( EConfigureRequestWindowSize, 
+                   I64LOW(transfer), I64HIGH(transfer) );
+
+    return SendReceive( EFlexTimerServConfigureRequest, args );
+    }
+
+// ---------------------------------------------------------------------------
+// Sets the window size in which alignment is possible for the timer.
+// This is a synchronous command. 64-bit function version.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt RFlexTimer::Configure( TTimeIntervalMicroSeconds aWindowSize )
+    {
+    OstTraceExt2( TRACE_NORMAL, DUP1_RFLEXTIMER_CONFIGURE,
+                  "RFlexTimer::Configure64;this=%x;aWindowSize=%lld",
+                  ( TUint )this, aWindowSize.Int64() );
+    
+    const TTimeIntervalMicroSeconds ZERO_INTERVAL64(0);
+    __ASSERT_ALWAYS(aWindowSize >= ZERO_INTERVAL64,
+                    User::Panic(KRFlexTimerPanicCat,
+                                EFlexTimerWindowLessThanZero));
+    
+    // Regardless of the user function, the window size is always transmitted
+    // as a 64-bit integer.
+    TIpcArgs args( EConfigureRequestWindowSize,
+                   I64LOW(aWindowSize.Int64()),
+                   I64HIGH(aWindowSize.Int64()) );
+
+    return SendReceive( EFlexTimerServConfigureRequest, args  );
+    }
+
+// ---------------------------------------------------------------------------
+// Gets the version number.
+// ---------------------------------------------------------------------------
+//
+TVersion RFlexTimer::Version() const
+    {
+    return ( TVersion( KFlexTimerServMajorVersionNumber,
+                       KFlexTimerServMinorVersionNumber,
+                       KFlexTimerServBuildVersionNumber ) );
+    }
+
+// ---------------------------------------------------------------------------
+// Connects to the server. If server does not exist, it is created.
+// ---------------------------------------------------------------------------
+//
+TInt RFlexTimer::StartServer()
+    {
+    OstTrace1( TRACE_NORMAL, RFLEXTIMER_STARTSERVER,
+               "RFlexTimer::StartServer;this=%x", ( TUint )this );
+    
+    TFindServer findServer( KFlexTimerServerName );
+    TFullName serverName;
+
+    // See if the server is already started. 
+    TInt ret = findServer.Next( serverName );
+    
+    if ( ret != KErrNone )
+        {
+        //Server was not found so create one.
+        RProcess serverProcess;
+        TBuf<1> serverParameters;
+
+        // Semaphore to guard the opening of the server process.
+        RSemaphore semaphore;
+
+        // Prevent two clients from  creating the serverProcess at the same
+        // time.
+        if ( ( ret = semaphore.CreateGlobal( 
+                KFlexTimerSemaphoreName, KPassFirstWaitEntry ) ) != KErrNone )
+            {
+            ret = semaphore.OpenGlobal( KFlexTimerSemaphoreName );
+            }
+
+        if ( ret == KErrNone )
+            {
+            semaphore.Wait();
+
+            // See again if the server is already started. This doublechecking
+            // is necessary, since two or processes may have resolved the
+            // first findserver before any server was created.
+
+            // TFindServer sets its content only when instantiated.
+            // Just using findServer.Next() does not work in here.
+            TFindServer findServerAgain( KFlexTimerServerName );
+            if ( findServerAgain.Next( serverName ) != KErrNone )
+                {
+                // Load the executable for the server.
+                ret = serverProcess.Create( KFlexTimerServerExe,
+                                            serverParameters,
+                                            EOwnerThread );
+
+                if ( ret == KErrNone )
+                    {
+                    // Server has been created successfully. It is initially 
+                    // in suspended state. Now resume the server process.
+                    serverProcess.Resume();
+
+                    // Wait until the server process has been started.
+                    TRequestStatus status;
+                    serverProcess.Rendezvous( status );
+                    User::WaitForRequest( status );
+
+                    // Check if server has panicked during initialization.
+                    ret = serverProcess.ExitType();
+                    if ( ret == EExitPanic )
+                        {
+                        OstTrace1( TRACE_NORMAL, DUP1_RFLEXTIMER_STARTSERVER,
+                                "RFlexTimer::StartServer;this=%x; "
+                                "ERROR: Server paniced",
+                                ( TUint )this );
+
+                        ret = KErrServerTerminated;
+                        }
+                    else
+                        {
+                        ret = status.Int();
+                        }
+
+                    // The server process stands on its own. This handle can
+                    // be closed. 
+                    serverProcess.Close();
+                    }
+                else
+                    {
+                    OstTrace1( TRACE_NORMAL, DUP2_RFLEXTIMER_STARTSERVER,
+                            "RFlexTimer::StartServer;this=%x; "
+                            "ERROR: Server creation failed",
+                            ( TUint )this );
+                    }
+                }
+            
+            semaphore.Signal();
+            semaphore.Close();
+            }
+        }
+
+    return ret;
+    }
+