diff -r 4816d766a08a -r f345bda72bc4 Symbian3/PDK/Source/GUID-6A4FE3A3-2E5D-51BB-8272-5995586291E9.dita --- a/Symbian3/PDK/Source/GUID-6A4FE3A3-2E5D-51BB-8272-5995586291E9.dita Tue Mar 30 11:42:04 2010 +0100 +++ b/Symbian3/PDK/Source/GUID-6A4FE3A3-2E5D-51BB-8272-5995586291E9.dita Tue Mar 30 11:56:28 2010 +0100 @@ -1,231 +1,231 @@ - - - - - -LCD -Extension Implementation Tutorial -

This topic describes how to create an LCD Extension.

-

The topic uses a reference board port named template_variant as -an example implementation.

-
Build environment

In the template reference board -port, the .mmp file for the LCD Extension is ...\template_variant\lcdtemplate.mmp. -This is one of the PRJ_MMPFILES referenced in the template -variant's bld.inf file in the ...\template_variant\... directory, -and means that the LCD Extension is built as part of the Variant.

The -source for the driver is contained entirely within ...\template_variant\specific\lcd.cpp.

The -driver is defined as a kernel extension and is loaded early in the boot sequence.

-
Initialization

The driver functionality is almost -entirely encapsulated by the DLcdPowerHandler class. This -is a power handler class derived from DPowerHandler. An -instance of DLcdPowerHandler is created when the extension -is loaded.

DLcdPowerHandler is defined within the -source file itself ...\template_variant\specific\lcd.cpp.

As -the driver is a kernel extension, it must have a DECLARE_STANDARD_EXTENSION() statement. -In the template port, this is implemented as follows:

DECLARE_STANDARD_EXTENSION() - { - __KTRACE_OPT(KPOWER,Kern::Printf("Starting LCD power manager")); - - // create LCD power handler - TInt r=KErrNoMemory; - DLcdPowerHandler* pH=new DLcdPowerHandler; - if (pH) - r=pH->Create(); - - __KTRACE_OPT(KPOWER,Kern::Printf("Returns %d",r)); - return r; - } -

This simply creates an instance of the DLcdPowerHandler class -and then calls its Create() function which implements the -display setup. This function should do the following:

    -
  • map the video RAM

  • -
  • setup the video info -structure

  • -
  • install the HAL handler

  • -
  • install the power handler.

  • -

Map -the video RAM

The frame buffer is a DPlatChunkHw object, -and should be mapped as globally accessible, readable and writeable. It should not be -mapped as writeback cached, it should be either not-cached or write-through. -The advantage of write through is that it allows the use of the write buffer.

TInt DLcdPowerHandler::Create() - { - ... - - // map the video RAM - TInt vSize = ((TemplateAssp*)Arch::TheAsic())->VideoRamSize(); - ivRamPhys = TTemplate::VideoRamPhys(); // EXAMPLE ONLY: assume TTemplate interface class - TInt r = DPlatChunkHw::New(iChunk,ivRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC); - if ® != KErrNone) - return r; - ... -

If the frame buffer resides in main RAM and there is no restriction -on which physical addresses may be used for it, physical RAM for the frame -buffer should be reserved by using Epoc::AllocPhysicalRam().

If -the frame buffer does not reside in main RAM, there is no problem about reserving -it.

If the frame buffer must reside at a specific address in main -RAM, there are two strategies available for reserving it:

    -
  • If no conflicts are -permitted between the frame buffer and memory allocations made during the -kernel boot (for example, if the frame buffer must reside at the end of main -memory), simply use Epoc::ClaimPhysicalRam(). This function -just marks a region of physical RAM as allocated, returning an error if any -part of the region has already been used.

  • -
  • The required physical -RAM region can be reserved in the bootstrap. The correct place to do this -is in the implementation of the boot table function BTF_Reserve when writing platform-specific source code for the bootstrap. -See the Bootstrap Port -Implementation Tutorial for more detail and look at ...\template_variant\bootstrap\template.s for -a concrete example.

  • -

Note that all Symbian platform base ports currently create a second -frame buffer for a secure screen. However, as platform security is not yet -implemented, this is wasteful of RAM and should be omitted.

Set up the video information -structure

The video information structure is used to define several -aspects of the display including display size, bits per pixel and address -of the frame buffer. This structure is the class TVideoInfoV01 defined -in the header file ...\eka\include\videodriver.h and -exported to ...\epoc32\include.

TInt DLcdPowerHandler::Create() - { - ... - // setup the video info structure, this will be used to remember the video settings - iVideoInfo.iDisplayMode = KConfigLcdInitialDisplayMode; - iVideoInfo.iOffsetToFirstPixel = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iOffsetToFirstVideoBuffer; - iVideoInfo.iIsPalettized = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iIsPalettized; - iVideoInfo.iOffsetBetweenLines = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iOffsetBetweenLines; - iVideoInfo.iBitsPerPixel = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iBitsPerPixel; - - iVideoInfo.iSizeInPixels.iWidth = KConfigLcdWidth; - iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight; - iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips; - iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips; - iVideoInfo.iIsMono = KConfigLcdIsMono; - iVideoInfo.iVideoAddress=(TInt)pV; - iVideoInfo.iIsPixelOrderLandscape = KConfigLcdPixelOrderLandscape; - iVideoInfo.iIsPixelOrderRGB = KConfigLcdPixelOrderRGB; - ... - }

Install -the HAL handler

Control of the display is done by using the HAL, -the Hardware Abstraction Layer.

The DLcdPowerHandler class -provides the implementation for the HAL handler for the HAL function group EHalGroupDisplay and -this needs to be registered with the kernel by calling Kern::AddHalEntry().

TInt DLcdPowerHandler::Create() - { - ... - // install the HAL function - r=Kern::AddHalEntry(EHalGroupDisplay, halFunction, this); - if (r!=KErrNone) - return r; - ... - }

See User-Side -Hardware Abstraction for more detailed information on the HAL.

Install the power handler

A call must be made to the Add() function, -which is supplied by the DPowerHandler base class of DLcdPowerHandler, -to register the handler with the power manager.

TInt DLcdPowerHandler::Create() - { - ... - // install the power handler - // power up the screen - Add(); - ... - }
-
HAL handler implementation

Requests to get and -set hardware attributes are made through calls to HAL::Get() and HAL::Set(). -These two HAL functions take a value that identifies a hardware attribute, -one of the HALData::TAttribute values.

For the -LCD Extension, the relevant hardware attributes are: EDisplayMode, EDisplayBitsPerPixel, EDisplayIsPalettized, EDisplayIsMono, EDisplayMemoryAddress, EDisplayMemoryHandle, EDisplayOffsetToFirstPixel, EDisplayOffsetBetweenLines, EDisplayXPixels, EDisplayYPixels, EDisplayPaletteEntry and EDisplayOffsetBetweenLines.

The HAL handler -is registered with the kernel as the handler for the THalFunctionGroup::EHalGroupDisplay group. -The HAL handler itself takes a function ID, which is one of the TDisplayHalFunction enumerators.

A -call to HAL::Get() and HAL::Set() that -takes one of the hardware attributes relevant to the LCD Extension is ultimately -routed to a call to this HAL handler function passing an appropriate function -ID. The association between the hardware attribute and the function ID is -the responsibility of the accessor functions.

See User-Side Hardware Abstraction for more information on the way this -works in general.

The HAL handler is implemented as a case statement, -switching on the function ID. For example, the following code fragment taken -from DLcdPowerHandler::HalFunction() gets and sets the brightness:

TInt DLcdPowerHandler::HalFunction(TInt aFunction, TAny* a1, TAny* a2) - { - TInt r=KErrNone; - switch(aFunction) - { - - ... - case EDisplayHalSetDisplayBrightness: - if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, - __PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetDisplayBrightness"))) - return KErrPermissionDenied; - r=SetBrightness(TInt(a1)); - break; - - case EDisplayHalDisplayBrightness: - kumemput32(a1,&iBrightness,sizeof(iBrightness)); - break; - ... -

where SetBrightness() is implemented as:

TInt DLcdPowerHandler::SetBrightness(TInt aValue) - { - __KTRACE_OPT(KEXTENSION,Kern::Printf("SetBrightness(%d)", aValue)); - - if (aValue >= KConfigLcdMinDisplayBrightness && aValue <= KConfigLcdMaxDisplayBrightness) - { - iBrightness=aValue; - - // TO DO: (mandatory) - // set the brightness - // - return KErrNone; - } - return KErrArgument; - } -

If an attribute does not have an implementation, the HAL handler -function should return KErrNotSupported.

For platform -security, the code only allows the attribute to be set if the current thread -has been authorized to write system data. Otherwise, it returns KErrPermissionDenied.

Switch on and switch off operations

All of the HAL operations -are seen to be synchronous by the user side. However there are some operations -such as turning the display on and off which may need to be implemented asynchronously.

The -display on/off code is implemented using synchronous kernel-side messages. -There is only one message per thread and the thread always blocks while a -message is outstanding. This means it is possible to make an asynchronous -operation appear synchronous.

When turning on the screen the kernel-side -message is queued and this thread is blocked until the message is completed, -which happens when the display has been turned on.

If a display needs -to be turned on and off truly asynchronously (for example, if millisecond -timer waits are required during the process of turning on the display), the -above functionality must be changed so that the complete occurs when the display -is truly on.

Accessing -the video information structure

When any part of the video information structure is read or written to, this must be done -within a critical section to prevent potential collisions with other threads -attempting to access the structure concurrently. A fast mutex is used to ensure -that only one thread can access the video information at any one time, as -the code segment below shows.

TInt DLcdPowerHandler::GetCurrentDisplayModeInfo(TVideoInfoV01& aInfo, TBool aSecure) - { - __KTRACE_OPT(KEXTENSION,Kern::Printf("GetCurrentDisplayModeInfo")); - NKern::FMWait(&iLock); - if (aSecure) - aInfo = iSecureVideoInfo; - else - aInfo = iVideoInfo; - NKern::FMSignal(&iLock); - return KErrNone; - } -
-
Power handler implementation

The DPowerHandler class -defines the interface that the driver must implement to provide power handling -behaviour. For the template reference board, the LCD Extension defines and -implements the DLcdPowerHandler class derived from DPowerHandler.

Note:

    -
  • DPowerHandler::PowerDown() and DPowerHandler::PowerUp()

    These functions are called in the context of the thread that initiates -power down or power up, and synchronization is required, typically by means -of power up and power down DFCs.

  • -
  • DPowerHandler::PowerUpLcd() and DPowerHandler::PowerDownLcd()

    These functions generally queue DFCs which then call platform-specific -functions to power the display up and down.

  • -
  • DPowerHandler::PowerUpDone() and DPowerHandler::PowerDownDone()

    When power up or down is complete, the interface supplies a set -of acknowledgment functions which must be called when the change of state -has taken place.

  • -
-
-LCD Extension -Architecture -Implementing -Dynamic DSA Allocation + + + + + +LCD +Extension Implementation Tutorial +

This topic describes how to create an LCD Extension.

+

The topic uses a reference board port named template_variant as +an example implementation.

+
Build environment

In the template reference board +port, the .mmp file for the LCD Extension is ...\template_variant\lcdtemplate.mmp. +This is one of the PRJ_MMPFILES referenced in the template +variant's bld.inf file in the ...\template_variant\... directory, +and means that the LCD Extension is built as part of the Variant.

The +source for the driver is contained entirely within ...\template_variant\specific\lcd.cpp.

The +driver is defined as a kernel extension and is loaded early in the boot sequence.

+
Initialization

The driver functionality is almost +entirely encapsulated by the DLcdPowerHandler class. This +is a power handler class derived from DPowerHandler. An +instance of DLcdPowerHandler is created when the extension +is loaded.

DLcdPowerHandler is defined within the +source file itself ...\template_variant\specific\lcd.cpp.

As +the driver is a kernel extension, it must have a DECLARE_STANDARD_EXTENSION() statement. +In the template port, this is implemented as follows:

DECLARE_STANDARD_EXTENSION() + { + __KTRACE_OPT(KPOWER,Kern::Printf("Starting LCD power manager")); + + // create LCD power handler + TInt r=KErrNoMemory; + DLcdPowerHandler* pH=new DLcdPowerHandler; + if (pH) + r=pH->Create(); + + __KTRACE_OPT(KPOWER,Kern::Printf("Returns %d",r)); + return r; + } +

This simply creates an instance of the DLcdPowerHandler class +and then calls its Create() function which implements the +display setup. This function should do the following:

    +
  • map the video RAM

  • +
  • setup the video info +structure

  • +
  • install the HAL handler

  • +
  • install the power handler.

  • +

Map +the video RAM

The frame buffer is a DPlatChunkHw object, +and should be mapped as globally accessible, readable and writeable. It should not be +mapped as writeback cached, it should be either not-cached or write-through. +The advantage of write through is that it allows the use of the write buffer.

TInt DLcdPowerHandler::Create() + { + ... + + // map the video RAM + TInt vSize = ((TemplateAssp*)Arch::TheAsic())->VideoRamSize(); + ivRamPhys = TTemplate::VideoRamPhys(); // EXAMPLE ONLY: assume TTemplate interface class + TInt r = DPlatChunkHw::New(iChunk,ivRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC); + if ® != KErrNone) + return r; + ... +

If the frame buffer resides in main RAM and there is no restriction +on which physical addresses may be used for it, physical RAM for the frame +buffer should be reserved by using Epoc::AllocPhysicalRam().

If +the frame buffer does not reside in main RAM, there is no problem about reserving +it.

If the frame buffer must reside at a specific address in main +RAM, there are two strategies available for reserving it:

    +
  • If no conflicts are +permitted between the frame buffer and memory allocations made during the +kernel boot (for example, if the frame buffer must reside at the end of main +memory), simply use Epoc::ClaimPhysicalRam(). This function +just marks a region of physical RAM as allocated, returning an error if any +part of the region has already been used.

  • +
  • The required physical +RAM region can be reserved in the bootstrap. The correct place to do this +is in the implementation of the boot table function BTF_Reserve when writing platform-specific source code for the bootstrap. +See the Bootstrap Port +Implementation Tutorial for more detail and look at ...\template_variant\bootstrap\template.s for +a concrete example.

  • +

Note that all Symbian platform base ports currently create a second +frame buffer for a secure screen. However, as platform security is not yet +implemented, this is wasteful of RAM and should be omitted.

Set up the video information +structure

The video information structure is used to define several +aspects of the display including display size, bits per pixel and address +of the frame buffer. This structure is the class TVideoInfoV01 defined +in the header file ...\eka\include\videodriver.h and +exported to ...\epoc32\include.

TInt DLcdPowerHandler::Create() + { + ... + // setup the video info structure, this will be used to remember the video settings + iVideoInfo.iDisplayMode = KConfigLcdInitialDisplayMode; + iVideoInfo.iOffsetToFirstPixel = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iOffsetToFirstVideoBuffer; + iVideoInfo.iIsPalettized = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iIsPalettized; + iVideoInfo.iOffsetBetweenLines = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iOffsetBetweenLines; + iVideoInfo.iBitsPerPixel = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iBitsPerPixel; + + iVideoInfo.iSizeInPixels.iWidth = KConfigLcdWidth; + iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight; + iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips; + iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips; + iVideoInfo.iIsMono = KConfigLcdIsMono; + iVideoInfo.iVideoAddress=(TInt)pV; + iVideoInfo.iIsPixelOrderLandscape = KConfigLcdPixelOrderLandscape; + iVideoInfo.iIsPixelOrderRGB = KConfigLcdPixelOrderRGB; + ... + }

Install +the HAL handler

Control of the display is done by using the HAL, +the Hardware Abstraction Layer.

The DLcdPowerHandler class +provides the implementation for the HAL handler for the HAL function group EHalGroupDisplay and +this needs to be registered with the kernel by calling Kern::AddHalEntry().

TInt DLcdPowerHandler::Create() + { + ... + // install the HAL function + r=Kern::AddHalEntry(EHalGroupDisplay, halFunction, this); + if (r!=KErrNone) + return r; + ... + }

See User-Side +Hardware Abstraction for more detailed information on the HAL.

Install the power handler

A call must be made to the Add() function, +which is supplied by the DPowerHandler base class of DLcdPowerHandler, +to register the handler with the power manager.

TInt DLcdPowerHandler::Create() + { + ... + // install the power handler + // power up the screen + Add(); + ... + }
+
HAL handler implementation

Requests to get and +set hardware attributes are made through calls to HAL::Get() and HAL::Set(). +These two HAL functions take a value that identifies a hardware attribute, +one of the HALData::TAttribute values.

For the +LCD Extension, the relevant hardware attributes are: EDisplayMode, EDisplayBitsPerPixel, EDisplayIsPalettized, EDisplayIsMono, EDisplayMemoryAddress, EDisplayMemoryHandle, EDisplayOffsetToFirstPixel, EDisplayOffsetBetweenLines, EDisplayXPixels, EDisplayYPixels, EDisplayPaletteEntry and EDisplayOffsetBetweenLines.

The HAL handler +is registered with the kernel as the handler for the THalFunctionGroup::EHalGroupDisplay group. +The HAL handler itself takes a function ID, which is one of the TDisplayHalFunction enumerators.

A +call to HAL::Get() and HAL::Set() that +takes one of the hardware attributes relevant to the LCD Extension is ultimately +routed to a call to this HAL handler function passing an appropriate function +ID. The association between the hardware attribute and the function ID is +the responsibility of the accessor functions.

See User-Side Hardware Abstraction for more information on the way this +works in general.

The HAL handler is implemented as a case statement, +switching on the function ID. For example, the following code fragment taken +from DLcdPowerHandler::HalFunction() gets and sets the brightness:

TInt DLcdPowerHandler::HalFunction(TInt aFunction, TAny* a1, TAny* a2) + { + TInt r=KErrNone; + switch(aFunction) + { + + ... + case EDisplayHalSetDisplayBrightness: + if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, + __PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetDisplayBrightness"))) + return KErrPermissionDenied; + r=SetBrightness(TInt(a1)); + break; + + case EDisplayHalDisplayBrightness: + kumemput32(a1,&iBrightness,sizeof(iBrightness)); + break; + ... +

where SetBrightness() is implemented as:

TInt DLcdPowerHandler::SetBrightness(TInt aValue) + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("SetBrightness(%d)", aValue)); + + if (aValue >= KConfigLcdMinDisplayBrightness && aValue <= KConfigLcdMaxDisplayBrightness) + { + iBrightness=aValue; + + // TO DO: (mandatory) + // set the brightness + // + return KErrNone; + } + return KErrArgument; + } +

If an attribute does not have an implementation, the HAL handler +function should return KErrNotSupported.

For platform +security, the code only allows the attribute to be set if the current thread +has been authorized to write system data. Otherwise, it returns KErrPermissionDenied.

Switch on and switch off operations

All of the HAL operations +are seen to be synchronous by the user side. However there are some operations +such as turning the display on and off which may need to be implemented asynchronously.

The +display on/off code is implemented using synchronous kernel-side messages. +There is only one message per thread and the thread always blocks while a +message is outstanding. This means it is possible to make an asynchronous +operation appear synchronous.

When turning on the screen the kernel-side +message is queued and this thread is blocked until the message is completed, +which happens when the display has been turned on.

If a display needs +to be turned on and off truly asynchronously (for example, if millisecond +timer waits are required during the process of turning on the display), the +above functionality must be changed so that the complete occurs when the display +is truly on.

Accessing +the video information structure

When any part of the video information structure is read or written to, this must be done +within a critical section to prevent potential collisions with other threads +attempting to access the structure concurrently. A fast mutex is used to ensure +that only one thread can access the video information at any one time, as +the code segment below shows.

TInt DLcdPowerHandler::GetCurrentDisplayModeInfo(TVideoInfoV01& aInfo, TBool aSecure) + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("GetCurrentDisplayModeInfo")); + NKern::FMWait(&iLock); + if (aSecure) + aInfo = iSecureVideoInfo; + else + aInfo = iVideoInfo; + NKern::FMSignal(&iLock); + return KErrNone; + } +
+
Power handler implementation

The DPowerHandler class +defines the interface that the driver must implement to provide power handling +behaviour. For the template reference board, the LCD Extension defines and +implements the DLcdPowerHandler class derived from DPowerHandler.

Note:

    +
  • DPowerHandler::PowerDown() and DPowerHandler::PowerUp()

    These functions are called in the context of the thread that initiates +power down or power up, and synchronization is required, typically by means +of power up and power down DFCs.

  • +
  • DPowerHandler::PowerUpLcd() and DPowerHandler::PowerDownLcd()

    These functions generally queue DFCs which then call platform-specific +functions to power the display up and down.

  • +
  • DPowerHandler::PowerUpDone() and DPowerHandler::PowerDownDone()

    When power up or down is complete, the interface supplies a set +of acknowledgment functions which must be called when the change of state +has taken place.

  • +
+
+LCD Extension +Architecture +Implementing +Dynamic DSA Allocation
\ No newline at end of file