--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/kernel/power.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,792 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32\kernel\power.cpp
+// Generic power management
+//
+//
+
+#include <kernel/kpower.h>
+#include <kernel/kern_priv.h>
+#include "execs.h"
+#include "msgqueue.h"
+
+// #define _DEBUG_POWER
+
+
+/******************************************************************************
+ * Power Manager - a Power Model implementation
+ ******************************************************************************/
+#ifndef __X86__
+DPowerController* TPowerController::ThePowerController = 0;
+#endif
+
+class DPowerManager : public DPowerModel
+ {
+public:
+ // from DPowerModel
+ void CpuIdle();
+ void RegisterUserActivity(const TRawEvent& anEvent);
+ TInt PowerHalFunction(TInt aFunction, TAny* a1, TAny* a2);
+ void AbsoluteTimerExpired();
+ void SystemTimeChanged(TInt anOldTime, TInt aNewTime);
+ TSupplyStatus MachinePowerStatus();
+
+public:
+
+ static DPowerManager* New();
+
+ TInt EnableWakeupEvents(TPowerState);
+ void DisableWakeupEvents();
+ void RequestWakeupEventNotification(TRequestStatus*);
+ void CancelWakeupEventNotification();
+ TInt PowerDown();
+
+ void AppendHandler(DPowerHandler*);
+ void RemoveHandler(DPowerHandler*);
+ void WakeupEvent();
+
+ DPowerController* iPowerController;
+ DBatteryMonitor* iBatteryMonitor;
+ DPowerHal* iPowerHal;
+
+ TInt iTotalCurrent;
+
+private:
+
+ DPowerManager();
+
+ // Acquire the feature lock
+ // Called in CS
+ void Lock()
+ {
+ Kern::MutexWait(*iFeatureLock);
+ }
+
+ // Release the feature lock
+ // Called in CS
+ void Unlock()
+ {
+ Kern::MutexSignal(*iFeatureLock);
+ }
+//
+// Currently not used
+//
+// #ifdef _DEBUG
+// TBool IsLocked()
+ // used in assertions only
+// { return iFeatureLock->iCleanup.iThread == TheCurrentThread; }
+// #endif
+
+ void NotifyWakeupEvent(TInt aReason);
+
+ DMutex* iFeatureLock;
+ DThread* iClient; // protected by the system lock
+ TClientRequest* iRequest; // protected by the system lock
+ DPowerHandler* iHandlers; // protected by the feature lock
+ };
+
+static DPowerManager* PowerManager;
+
+class DummyPowerController : public DPowerController
+ // Used when the plaform doesn't support power management
+ {
+public: // from DPowerController
+ void CpuIdle() {}
+ void EnableWakeupEvents() { WakeupEvent(); }
+ void DisableWakeupEvents() {}
+ void AbsoluteTimerExpired() {}
+ void PowerDown(TTimeK /* aWakeupTime */) { if (iTargetState == EPwOff) __PM_PANIC("Can't power off"); }
+ };
+
+TInt PowerModelInit()
+ {
+#ifdef _DEBUG_POWER
+ TInt maskIndex = KPOWER / 32;
+ TUint32 bitMask = 1 << (KPOWER % 32);
+ TheSuperPage().iDebugMask[maskIndex] |= bitMask;
+#endif
+ __KTRACE_OPT2(KBOOT,KPOWER,Kern::Printf("PowerModelInit()"));
+ DPowerManager* pm = DPowerManager::New();
+ if (!pm)
+ return KErrNoMemory;
+ PowerManager = pm;
+ return KErrNone;
+ }
+
+_LIT(KPowerMgrMutexName, "PwrMgrLock");
+
+DPowerManager* DPowerManager::New()
+ {
+ DPowerManager* self = new DPowerManager();
+ if (!self)
+ return NULL;
+ if (Kern::MutexCreate(self->iFeatureLock, KPowerMgrMutexName, KMutexOrdPowerMgr) != KErrNone)
+ return NULL; // Do not cleanup since kernel will panic eventually
+ self->iPowerController = new DummyPowerController();
+ if (self->iPowerController == NULL)
+ return NULL; // Do not cleanup since kernel will panic eventually
+ TInt r = Kern::CreateClientRequest(self->iRequest);
+ if (r != KErrNone)
+ return NULL; // Do not cleanup since kernel will panic eventually
+ return self;
+ }
+
+DPowerManager::DPowerManager()
+ {
+ }
+
+void DPowerManager::CpuIdle()
+ { // from DPowerModel
+ __PM_ASSERT(iPowerController);
+ iPowerController->CpuIdle();
+ }
+
+void DPowerManager::RegisterUserActivity(const TRawEvent&)
+ { // from DPowerModel
+ }
+
+void DPowerManager::SystemTimeChanged(TInt aOldTime, TInt aNewTime)
+ { // from DPowerModel
+ if (iBatteryMonitor)
+ iBatteryMonitor->SystemTimeChanged(aOldTime, aNewTime);
+ }
+
+TSupplyStatus DPowerManager::MachinePowerStatus()
+ { // from DPowerModel
+ TSupplyStatus s;
+ if (iBatteryMonitor)
+ s = iBatteryMonitor->MachinePowerStatus();
+ else
+ s = EGood;
+ return s;
+ }
+
+TInt DPowerManager::PowerHalFunction(TInt aFunction, TAny* a1, TAny* a2)
+ { // from DPowerModel
+ __KTRACE_OPT(KPOWER,Kern::Printf(">DPowerManager::PowerHalFunction() func=0x%x, a1=0x%x, a2=0x%x", aFunction, a1, a2));
+ TInt r;
+ if (iPowerHal)
+ r = iPowerHal->PowerHalFunction(aFunction, a1, a2);
+ else
+ r = KErrNotSupported;
+
+ __KTRACE_OPT(KPOWER,Kern::Printf("<DPowerManager::PowerHalFunction() return 0x%x", r));
+ return r;
+ }
+
+void DPowerManager::AbsoluteTimerExpired()
+ { // from DPowerModel
+ if (iPowerController->iTargetState != EPwActive)
+ iPowerController->AbsoluteTimerExpired();
+ }
+
+// Called in CS
+void DPowerManager::AppendHandler(DPowerHandler* aPh)
+ { // called by drivers (power handler)
+ __KTRACE_OPT(KPOWER,Kern::Printf("PowerManger::AppendHandler('%lS')", &aPh->iName));
+ __ASSERT_CRITICAL;
+ //Check to ensure that handler is not added multiple times and not part of any other list
+ __PM_ASSERT(!(aPh->iPrev) && !(aPh->iNext));
+ Lock();
+ //Create circular doubly linked power handler list
+ if(iHandlers == NULL)
+ { //Empty list, create first entry
+ iHandlers = aPh;
+ aPh->iNext = iHandlers;
+ aPh->iPrev = iHandlers;
+ }
+ else
+ { //Append to end of the list.
+ aPh->iNext = iHandlers->iNext;
+ iHandlers->iNext->iPrev = aPh;
+ aPh->iPrev = iHandlers;
+ iHandlers->iNext = aPh;
+ iHandlers = aPh;
+ }
+ Unlock();
+ }
+
+// Called in CS
+void DPowerManager::RemoveHandler(DPowerHandler* aPh)
+ { // called by drivers (power handler)
+ __KTRACE_OPT(KPOWER,Kern::Printf("PowerManger::RemoveHandler('%lS')", &aPh->iName));
+ __ASSERT_CRITICAL;
+ Lock();
+ __PM_ASSERT(aPh);
+
+ if ((iHandlers == NULL) //If the list is empty
+ || (aPh->iNext == NULL || aPh->iPrev == NULL)) //or entry already removed then return immediately
+ {
+ aPh->iPrev = aPh->iNext = NULL;
+ Unlock();
+ return;
+ }
+
+ DPowerHandler *temp = aPh->iPrev;
+ if(aPh == temp) //Only one node in the list.
+ iHandlers = NULL;
+ else
+ { //Remove the entry from list
+ temp->iNext = aPh->iNext;
+ temp = aPh->iNext;
+ temp->iPrev = aPh->iPrev;
+ if(aPh == iHandlers) //If the node is the last node in the list then make iHandler point to last one.
+ iHandlers = aPh->iPrev;
+ }
+ //Make next and prev pointers to NULL
+ aPh->iPrev = aPh->iNext = NULL;
+ Unlock();
+ }
+
+void DPowerManager::WakeupEvent()
+ { // called by power controller
+ __KTRACE_OPT(KPOWER,Kern::Printf("PowerManger::WakeupEvent()"));
+ if (iPowerController->iTargetState != EPwActive)
+ {
+ NKern::ThreadEnterCS();
+ NotifyWakeupEvent(KErrNone);
+ NKern::ThreadLeaveCS();
+ }
+ }
+
+TInt DPowerManager::EnableWakeupEvents(TPowerState aState)
+ { // called by ExecHandler
+ __KTRACE_OPT(KPOWER,Kern::Printf("PowerManger::EnableWakeupEvents(0x%x)", aState));
+ if ((aState < 0) || (EPwLimit <= aState))
+ return KErrArgument;
+ if (aState == EPwActive)
+ return KErrArgument;
+ Lock();
+ if (iPowerController->iTargetState != EPwActive)
+ iPowerController->DisableWakeupEvents();
+ iPowerController->iTargetState = aState;
+ iPowerController->EnableWakeupEvents();
+ Unlock();
+ return KErrNone;
+ }
+
+void DPowerManager::DisableWakeupEvents()
+ { // called by ExecHandler
+ __KTRACE_OPT(KPOWER,Kern::Printf("PowerManger::DisableWakeupEvents()"));
+ Lock();
+ if (iPowerController->iTargetState != EPwActive)
+ {
+ iPowerController->iTargetState = EPwActive;
+ iPowerController->DisableWakeupEvents();
+ }
+ Unlock();
+ }
+
+void DPowerManager::RequestWakeupEventNotification(TRequestStatus* aStatus)
+ { // called by ExecHandler
+ __KTRACE_OPT(KPOWER,Kern::Printf("PowerManger::RequestWakeupEventNotification()"));
+ Lock(); // we aquire this lock to avoid new requests while in PowerDown
+ NKern::LockSystem();
+ if (iClient || iRequest->SetStatus(aStatus) != KErrNone)
+ Kern::RequestComplete(aStatus, KErrInUse);
+ else
+ {
+ iClient = TheCurrentThread;
+ iClient->Open();
+ }
+ NKern::UnlockSystem();
+ Unlock();
+ __KTRACE_OPT(KPOWER,Kern::Printf("<PowerManger::RequestWakeupEventNotification()"));
+ }
+
+void DPowerManager::NotifyWakeupEvent(TInt aReason)
+ { // private
+ NKern::LockSystem();
+ DThread* client = iClient;
+ if (!client)
+ {
+ NKern::UnlockSystem();
+ return;
+ }
+ iClient = NULL;
+ Kern::QueueRequestComplete(client, iRequest, aReason);
+ NKern::UnlockSystem();
+ client->Close(NULL);
+ }
+
+void DPowerManager::CancelWakeupEventNotification()
+ { // called by ExecHandler
+ __KTRACE_OPT(KPOWER,Kern::Printf("PowerManger::CancelWakeupEventNotification()"));
+ NKern::ThreadEnterCS();
+ NotifyWakeupEvent(KErrCancel);
+ NKern::ThreadLeaveCS();
+ }
+
+// Called in CS
+TInt DPowerManager::PowerDown()
+ { // called by ExecHandler
+ __KTRACE_OPT(KPOWER,Kern::Printf(">PowerManger::PowerDown(0x%x) Enter", iPowerController->iTargetState));
+ __ASSERT_CRITICAL;
+
+ Lock();
+
+
+ if (iPowerController->iTargetState == EPwActive)
+ {
+ Unlock();
+ return KErrNotReady;
+ }
+
+ __PM_ASSERT(iHandlers);
+ NFastSemaphore sem(0);
+ DPowerHandler* ph = iHandlers;
+ //Power down in reverse order of handle registration.
+ do
+ {
+#ifdef _DEBUG_POWER
+ __PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
+#endif
+ ph->iSem = &sem;
+ ph->PowerDown(iPowerController->iTargetState);
+#ifdef _DEBUG_POWER
+ __PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
+ NKern::FSWait(&sem); // power down drivers one after another to simplify debug
+ __PM_ASSERT(!ph->iSem);
+ __PM_ASSERT(ph->iStatus & EDone);
+ ph->iStatus &= ~EDone;
+#endif
+ ph = ph->iPrev;
+ }while(ph != iHandlers);
+
+#ifndef _DEBUG_POWER
+ ph = iHandlers;
+ do
+ {
+ NKern::FSWait(&sem);
+ ph = ph->iPrev;
+ }while(ph != iHandlers);
+#endif
+
+ TTickQ::Wait();
+
+ iPowerController->PowerDown(K::SecondQ->WakeupTime());
+ __PM_ASSERT(iPowerController->iTargetState != EPwOff);
+ iPowerController->iTargetState = EPwActive;
+
+ K::SecondQ->WakeUp();
+ TTickQ::Signal();
+
+ ph = iHandlers->iNext;
+ //Power up in same order of handle registration.
+ do
+ {
+#ifdef _DEBUG_POWER
+ __PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
+#endif
+ ph->iSem = &sem;
+ ph->PowerUp();
+#ifdef _DEBUG_POWER
+ __PM_ASSERT(!(ph->iStatus & DPowerHandler::EDone));
+ NKern::FSWait(&sem); // power down drivers one after another to simplify debug
+ __PM_ASSERT(!ph->iSem);
+ __PM_ASSERT(ph->iStatus & EDone);
+ ph->iStatus &= ~EDone;
+#endif
+ ph = ph->iNext;
+ }while(ph != iHandlers->iNext);
+
+#ifndef _DEBUG_POWER
+ ph = iHandlers->iNext;
+ do
+ {
+ NKern::FSWait(&sem);
+ ph = ph->iNext;
+ }while(ph != iHandlers->iNext);
+#endif
+
+ // complete wakeup notification request if any
+ NotifyWakeupEvent(KErrNone);
+
+ Unlock();
+
+ __KTRACE_OPT(KPOWER,Kern::Printf("<PowerManger::PowerDown() Leave"));
+
+ return KErrNone;
+ }
+
+/******************************************************************************
+ * Power Handlers
+ ******************************************************************************/
+
+
+
+/**
+Constructor.
+
+@param aName The power handler's debug-purpose symbolic name.
+
+@pre Calling thread must be in a critical section.
+@pre No fast mutex can be held.
+@pre Call in a thread context.
+@pre Kernel must be unlocked
+@pre interrupts enabled
+*/
+EXPORT_C DPowerHandler::DPowerHandler(const TDesC& aName) : iName(aName)
+ {
+ CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"DPowerHandler::DPowerHandler");
+ }
+
+
+
+/**
+Destructor.
+
+@pre Calling thread must be in a critical section.
+@pre No fast mutex can be held.
+@pre Call in a thread context.
+@pre Kernel must be unlocked
+@pre interrupts enabled
+*/
+EXPORT_C DPowerHandler::~DPowerHandler()
+ {
+ CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"DPowerHandler::~DPowerHandler");
+ SetCurrentConsumption(0);
+ }
+
+
+
+/**
+Registers the power handler with the power manager.
+
+After registration, the power manager notifies the device driver about
+power state transitions by calling PowerDown() & PowerUp() in this power
+handler's interface.
+
+Note that the implementation of Add() acquires an internal lock (a DMutex),
+which is also held when the power manager calls PowerDown() and PowerUp().
+This means that the device driver cannot hold a lock over Add() calls if
+the same lock is acquired by PowerDown() and PowerUp() implementations.
+
+You can find an example of synchronization between outgoing Add()
+and incoming PowerDown() & PowerUp() in e32/drivers/ecomm/d_comm.cpp.
+
+@see DPowerHandler::Remove()
+
+@pre Calling thread must be in a critical section.
+@pre No fast mutex can be held.
+@pre Call in a thread context.
+@pre Kernel must be unlocked
+@pre interrupts enabled
+*/
+EXPORT_C void DPowerHandler::Add()
+ {
+ CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"DPowerHandler::Add");
+ PowerManager->AppendHandler(this);
+ }
+
+
+
+
+/**
+De-registers the power handler.
+
+After the call to this function completes, the power manager stops notifying
+the device driver about kernel power state transitions.
+
+Note that the implementation of Remove() acquires an internal lock (a DMutex),
+which is also held when the power manager calls PowerDown() and PowerUp().
+This means that the device driver cannot hold a lock over Remove() calls if
+the same lock is acquired by PowerDown() and PowerUp() implementations.
+
+You can find an example of synchronization between outgoing Remove()
+and incoming PowerDown() & PowerUp() in e32/drivers/ecomm/d_comm.cpp.
+
+@see DPowerHandler::Add()
+
+@pre Calling thread must be in a critical section.
+@pre No fast mutex can be held.
+@pre Call in a thread context.
+@pre Kernel must be unlocked
+@pre interrupts enabled
+*/
+EXPORT_C void DPowerHandler::Remove()
+ {
+ CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"DPowerHandler::Remove");
+ PowerManager->RemoveHandler(this);
+ }
+
+
+void DPowerHandler::Done()
+ { // private
+#ifdef _DEBUG_POWER
+ __PM_ASSERT(!(iStatus & EDone));
+ iStatus |= EDone;
+#endif
+ NKern::Lock();
+ __KTRACE_OPT(KPOWER,Kern::Printf("DPowerHandler::Done('%lS') sem=0x%x", &iName, iSem));
+ NFastSemaphore* sem = (NFastSemaphore*)__e32_atomic_swp_ord_ptr(&iSem, 0);
+ if (sem)
+ sem->Signal();
+ NKern::Unlock();
+ }
+
+
+
+
+/**
+Signals power up completion.
+
+A device driver calls this function precisely once in response to a PowerUp() call.
+It can be called by any thread at any time after PowerUp() has been entered.
+
+@pre No fast mutex can be held.
+@pre Call in a thread context.
+@pre Kernel must be unlocked
+@pre interrupts enabled
+*/
+EXPORT_C void DPowerHandler::PowerUpDone()
+ {
+ CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DPowerHandler::PowerUpDone");
+ Done();
+ }
+
+
+
+/**
+Signals power down completion.
+
+A device driver calls this function precisely once in response to a PowerDown() call.
+It can be called by any thread at any time after PowerDown() has been entered.
+
+@pre No fast mutex can be held.
+@pre Call in a thread context.
+@pre Kernel must be unlocked
+@pre interrupts enabled
+*/
+EXPORT_C void DPowerHandler::PowerDownDone()
+ {
+ CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DPowerHandler::PowerDownDone");
+ Done();
+ }
+
+
+
+/** @deprecated, no replacement */
+EXPORT_C void DPowerHandler::DeltaCurrentConsumption(TInt aDelta)
+ {
+ __e32_atomic_add_ord32(&iCurrent, aDelta);
+ __PM_ASSERT(iCurrent >= 0);
+ __e32_atomic_add_ord32(&PowerManager->iTotalCurrent, aDelta);
+ __PM_ASSERT(PowerManager->iTotalCurrent >= 0);
+ }
+
+/** @deprecated, no replacement */
+EXPORT_C void DPowerHandler::SetCurrentConsumption(TInt aCurrent)
+ {
+ __PM_ASSERT(aCurrent >= 0);
+ TInt old = (TInt)__e32_atomic_swp_ord32(&iCurrent, aCurrent);
+ TInt delta = aCurrent - old;
+ __e32_atomic_add_ord32(&PowerManager->iTotalCurrent, delta);
+ __PM_ASSERT(PowerManager->iTotalCurrent >= 0);
+ }
+
+/******************************************************************************
+ * Power Controller
+ ******************************************************************************/
+
+
+
+
+/**
+Default constructor.
+
+Typically a variant implementation creates a power controller object at
+variant initialization time.
+
+Only one power controller can be created.
+
+The object can never be destroyed.
+
+@pre Calling thread must be in a critical section.
+@pre No fast mutex can be held.
+@pre Call in a thread context.
+@pre Kernel must be unlocked
+@pre interrupts enabled
+*/
+EXPORT_C DPowerController::DPowerController()
+ {
+ CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"DPowerController::DPowerController");
+ iTargetState = EPwActive;
+#ifndef __X86__
+ iResourceControllerData.iResourceController = NULL;
+ iResourceControllerData.iClientId = -1;
+#endif
+ }
+
+/**
+Registers this power controller object with the power manager.
+
+The power manager can only use the power controller after registration.
+
+@pre Calling thread must be in a critical section.
+@pre No fast mutex can be held.
+@pre Call in a thread context.
+@pre Kernel must be unlocked
+@pre interrupts enabled
+*/
+EXPORT_C void DPowerController::Register()
+ {
+ CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"DPowerController::Register");
+ __KTRACE_OPT2(KBOOT,KPOWER,Kern::Printf("DPowerController::Register()"));
+ delete PowerManager->iPowerController;
+ PowerManager->iPowerController = this;
+#ifndef __X86__
+ TPowerController::ThePowerController = this;
+#endif
+ K::PowerModel = PowerManager;
+ }
+
+#ifndef __X86__
+/**
+Registers resource controller with power controller
+This function is called only by resource controller to register itself with power controller
+*/
+EXPORT_C TInt DPowerController::RegisterResourceController(DBase* aController, TInt aClientId)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("DPowerController::Register()"));
+ if(iResourceControllerData.iResourceController)
+ return KErrAlreadyExists;
+ //Store the Resource controller pointer
+ iResourceControllerData.iResourceController = aController;
+ //Store the client Id generated by Resource controller for Power controller to use.
+ iResourceControllerData.iClientId = aClientId;
+ return KErrNone;
+ }
+
+/**
+ Interface class to give access to the power controller to base port components.
+*/
+EXPORT_C DPowerController* TPowerController::PowerController()
+ {
+ return TPowerController::ThePowerController;
+ }
+#endif
+
+/**
+Signals a wakeup event.
+
+The power controller must signal wakeup events when enabled,
+through EnableWakeupEvents() and DisableWakeupEvents(), and
+when iTargetState is not equal to EPwActive.
+
+@see DPowerController::iTargetState
+
+@pre Calling thread must be in a critical section.
+@pre No fast mutex can be held.
+@pre Call in a thread context.
+@pre Kernel must be unlocked
+@pre interrupts enabled
+*/
+EXPORT_C void DPowerController::WakeupEvent()
+ {
+ CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"DPowerController::WakeupEvent");
+ PowerManager->WakeupEvent();
+ }
+
+
+/******************************************************************************
+ * Battery Monitor
+ ******************************************************************************/
+
+EXPORT_C DBatteryMonitor::DBatteryMonitor()
+ {
+ }
+
+EXPORT_C void DBatteryMonitor::Register()
+ {
+ __KTRACE_OPT2(KBOOT,KPOWER,Kern::Printf("DBatteryMonitor::Register()"));
+ PowerManager->iBatteryMonitor = this;
+ }
+
+/******************************************************************************
+ * Power Hal
+ ******************************************************************************/
+
+EXPORT_C DPowerHal::DPowerHal()
+ {
+ }
+
+EXPORT_C void DPowerHal::Register()
+ {
+ __KTRACE_OPT2(KBOOT,KPOWER,Kern::Printf("DPowerHal::Register()"));
+ PowerManager->iPowerHal = this;
+ }
+
+/******************************************************************************
+ * Kern
+ ******************************************************************************/
+
+/** Checks power status
+ @return ETrue if status is good, EFalse otherwise
+*/
+
+EXPORT_C TBool Kern::PowerGood()
+ {
+ return K::PowerGood;
+ }
+
+/******************************************************************************
+ * Exec Handlers
+ ******************************************************************************/
+
+TInt ExecHandler::PowerEnableWakeupEvents(TPowerState aState)
+ {
+ if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Power::EnableWakeupEvents")))
+ K::UnlockedPlatformSecurityPanic();
+ NKern::ThreadEnterCS();
+ TInt r = PowerManager->EnableWakeupEvents(aState);
+ NKern::ThreadLeaveCS();
+ return r;
+ }
+
+void ExecHandler::PowerDisableWakeupEvents()
+ {
+ if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Power::DisableWakeupEvents")))
+ K::UnlockedPlatformSecurityPanic();
+ NKern::ThreadEnterCS();
+ PowerManager->DisableWakeupEvents();
+ NKern::ThreadLeaveCS();
+ }
+
+void ExecHandler::PowerRequestWakeupEventNotification(TRequestStatus* aStatus)
+ {
+ if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Power::RequestWakeupEventNotification")))
+ K::UnlockedPlatformSecurityPanic();
+ NKern::ThreadEnterCS();
+ PowerManager->RequestWakeupEventNotification(aStatus);
+ NKern::ThreadLeaveCS();
+ }
+
+void ExecHandler::PowerCancelWakeupEventNotification()
+ {
+ if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Power::CancelWakeupEventNotification")))
+ K::UnlockedPlatformSecurityPanic();
+ PowerManager->CancelWakeupEventNotification();
+ }
+
+TInt ExecHandler::PowerDown()
+ {
+ if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Power::PowerDown")))
+ K::UnlockedPlatformSecurityPanic();
+ NKern::ThreadEnterCS();
+ TInt r = PowerManager->PowerDown();
+ NKern::ThreadLeaveCS();
+ return r;
+ }
+