diff -r 578be2adaf3e -r 307f4279f433 Adaptation/GUID-A789E0D6-74B2-517D-B73A-F9B11794F175.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adaptation/GUID-A789E0D6-74B2-517D-B73A-F9B11794F175.dita Fri Oct 15 14:32:18 2010 +0100 @@ -0,0 +1,160 @@ + + + + + +Peripheral Driver Power Implementation TutorialDescribes an implementation of the DPowerHandler class. +

Peripheral driver power management is based on the DPowerHandler class. This is a class that defines the interface that the driver +must provide to the generic kernel side power manager.

+

The class also provides the necessary support functions. The class +is defined as:

+class DPowerHandler : public DBase + { +public: + IMPORT_C ~DPowerHandler(); +public: + IMPORT_C DPowerHandler(const TDesC& aName); + IMPORT_C void Add(); + IMPORT_C void Remove(); + IMPORT_C void PowerUpDone(); + IMPORT_C void PowerDownDone(); + IMPORT_C void SetCurrentConsumption(TInt aCurrent); + IMPORT_C void DeltaCurrentConsumption(TInt aCurrent); +public: + virtual void PowerDown(TPowerState aTargetState) = 0; + virtual void PowerUp() = 0; +private: + ... + }; + +

Typically, at least one power handler object is implemented by +the peripheral driver. In some cases the peripheral driver interface +class may derive from DPowerHandler, in others +it creates and owns an instance of a DPowerHandler derived class.

+

The first eight functions are exported from the kernel, EKERN.EXE, while the remaining two pure virtual functions +are implemented by the peripheral driver.

+ +

Notes:

+
    +
  1. Current consumption +monitoring does not have a full implementation in the power manager +at present. It is unclear whether this will be ever required. However, DPowerHandler does provide two functions: DPowerHandler::SetCurrentConsumption() and DPowerHandler::DeltaCurrentConsumption() that +a power handler can use to track the peripheral's power consumption. +Note that this is not based on actual measurements.

    SetCurrentConsumption() sets a target current consumption, +usually at driver creation time.

    DeltaCurrentConsumption() changes this target current consumption value, specifying a positive +or a negative value as appropriate; this might be called in response +to an operation that is about to start.

    Although we have described +the context in which these functions would be used, we recommend that +you do not use them.

  2. +
  3. Fixed media +drivers do not have a power handler. This means there is currently +no mechanism to power down media drivers and the associated fixed +media when the system transitions to a low power state.

  4. +
  5. The __NEW_POWER_HANDLERS macro is used to maintain backwards +compatibility with the power model used in previous versions of Symbian +platform. If this macro is not defined, it is possible for +power handlers to revert back to the behavior they present in Kernel +Architecture 1 (EKA1).

    If implementing an old style power +handler, the following functions will have to have an implementation +provided by the peripheral driver:

    virtual TInt DoPowerUp() +virtual void DoPowerDown(TUint32 /* aPowerDownMask */) +virtual void DoEmergencyPowerDown() +

    If using at least an old style power handler +the power manager will not complete any powering down (transition +to Off or Standby). Thus it is recommended that they +not be used.

  6. +
+
DPowerHandler::PowerDown() virtual void PowerDown(TPowerState) = 0;

When is it called?

DPowerHandler::PowerDown() is called by the Power manager during a transition to the Standby or +the Off state. The TPowerState argument +specifies which of the two power states is the target.

Implementation issues

    +
  1. After receiving +a request to power down, as a result of a system transition to the Standby or Off states, a peripheral driver should perform +the necessary activity to power down the peripheral and ancillary +hardware, unless it is required for the detection of wake-up events. +This activity might include requesting the removal of the power supply +and any other power resources.

  2. +
  3. The power down +operation can be done in the same thread in which PowerDown() runs, i.e. synchronously, or it can run in another thread, i.e. +asynchronously. You would probably implement power down in another +thread if the operation were potentially slow. Once the peripheral +has powered down, it must inform the power manager by calling DPowerHandler::PowerDownDone(), and this function can be +called from the same thread in which PowerDown() runs, +or it can be called from another thread. Two points to note:

      +
    • PowerDownDone() can be called before or after PowerDown() returns

    • +
    • PowerDownDone() cannot be called before PowerDown() has been entered.

    • +
  4. +
  5. PowerDown() is only called on a transition to the Standby or the Off state. If the peripheral hardware is powered down when the peripheral +driver is closed, or when the hardware resources are relinquished +by the driver, then this is managed by the driver alone.

  6. +
  7. There are synchronisation +issues related to calls to the DPowerHandler::Add() and DPowerHandler::Remove() functions. DPowerHandler::Add() is called by the peripheral driver +when the driver object is created. This registers the power handler +with the power manager so that so that the driver can receive notification +of power state transitions. Conversely, DPowerHandler::Remove() is called when the peripheral driver is in the process of being +destroyed. This de-registers the power handler so that the driver +is no longer notified of power state transitions. Calls to DPowerHandler::Add(), DPowerHandler::Remove(), DPowerHandler::PowerDown() and DPowerHandler::PowerUp() can run asynchronously in relation to one another. For example, +it is entirely possible that the kernel may be asking the driver to +power down while it is being created, or indeed while it is being +destroyed.

    To avoid deadlock, DPowerHandler::Add(), DPowerHandler::Remove(), and the Power manager functions that call your DPowerHandler::PowerDown() and your DPowerHandler::PowerUp() functions, +all acquire a lock, a DMutex. While the lock itself +is internal to Symbian platform, it does impose a requirement that:

      +
    • DPowerHandler::Add()

    • +
    • DPowerHandler::Remove()

    • +
    • DPowerHandler::PowerDown()

    • +
    • DPowerHandler::PowerUp()

    • +

    all run in the same thread. A common implementation of DPowerHandler::PowerDown(), therefore, schedules a DFC +to run on the same thread (a DFC queue) as the one that calls DPowerHandler::Add() and DPowerHandler::Remove().

  8. +
+
DPowerHandler::PowerUp() virtual void PowerUp() = 0;

When is it called?

DPowerHandler::PowerUp() is called by the Power manager during a transition from the Standby state +back to the Active state. It is up to the peripheral driver +to decide whether or not to power up the peripheral.

Implementation +issues

    +
  1. After receiving +a notification to power up, as a result of a system transition from +the Standby to the Active state, it is up to the peripheral +driver to decide whether or not to power up the peripheral and ancillary +hardware. The decision usually depends on whether or not the peripheral +driver is currently in use.

  2. +
  3. The power up +operation can be done in the same thread in which PowerUp() runs, i.e. synchronously, or it can run in another thread, i.e. +asynchronously. You would probably implement power up in another thread +if the operation were potentially slow. Whether or not the peripheral +driver intends to power up immediately, it must acknowledge the power +up request by calling DPowerHandler::PowerUpDone(), and this function can be called from the same thread in which PowerUp() runs, or it can be called from another thread. +Two points to note:

      +
    • PowerUpDone() can be called before or after PowerUp() returns

    • +
    • PowerUpDone() cannot be called before PowerUp() has been entered.

    • +
  4. +
  5. PowerUp() is only called on a transition to the Active state. If the +peripheral hardware is powered up when the peripheral driver is opened, +or when the hardware resources are first used by the driver, then +this is managed by the driver alone.

  6. +
  7. There are synchronisation +issues related to calls to the DPowerHandler::Add() and DPowerHandler::Remove() functions. DPowerHandler::Add() is called by the peripheral driver +when the driver object is created. This registers the power handler +with the power manager so that so that the driver can receive notification +of power state transitions. Conversely, DPowerHandler::Remove() is called when the peripheral driver is in the process of being +destroyed. This de-registers the power handler so that the driver +is no longer notified of power state transitions. Calls to DPowerHandler::Add(), DPowerHandler::Remove(), DPowerHandler::PowerDown() and DPowerHandler::PowerUp() can run asynchronoulsy in relation to one another. For example, +it is entirely possible that the kernel may be asking the driver to +power down while it is being created, or indeed while it is being +destroyed.

    To avoid deadlock, DPowerHandler::Add(), DPowerHandler::Remove(), and the power manager functions that call your DPowerHandler::PowerDown() and your DPowerHandler::PowerUp() functions, +all acquire a lock, a DMutex. While the lock itself +is internal to Symbian platform, it does impose a requirement that:

      +
    • DPowerHandler::Add()

    • +
    • DPowerHandler::Remove()

    • +
    • DPowerHandler::PowerDown()

    • +
    • DPowerHandler::PowerUp()

    • +

    all run in the same thread. A common implementation of DPowerHandler::PowerUp(), therefore, schedules a DFC to +run on the same thread (a DFC queue) as the one that calls DPowerHandler::Add() and DPowerHandler::Remove().

  8. +
+
\ No newline at end of file