Windows CE LCD显示驱动简析(1)(基于WinCE5.0 SMDK2410 BSP的LCD显示设备驱动)

SMDK2410 BSP(CE5.0,6.0中是DEVICEEMULATOR)已经实现了一个显示驱动,对应的GPE继承类是S3C2410DISP.
首先简单介绍下WinCE的显示驱动架构,然和分析了需要用户开发的显示驱动部分GPE(或者DDGPE)继承类.以下内容参考了MS帮助和<Windows CE工程实践完全解析>一书.

1.Windows CE显示驱动架构
Windows CE的显示设备驱动接口(DDI)是Windows NT DDI的一个子集.
显示驱动由Gwes.exe调用和加载,图形初级引擎 (GPE)用来处理默认的绘图工作,在驱动模型中扮演上层的模型设备驱动(MDD).用户需要开发的就是下层的平台相关驱动(PDD)和硬件相关的代码.
调用的依次顺序是Application,Coredll.dll,Gwes.exe,Ddi.dll,Hardware.
其中Ddi.dll就是默认的显示驱动名称.和大部分dll一样,Ddi.dll会导出相应的函数供上层调用.Ddi.dll只导出DrvEnableDriver函数,这个函数返回一个指向含有27个函数指针结构(DRVENABLEDATA)的指针.当GWES调用显示驱动,它就会相应调用这27个函数.开发显示驱动就包括开发这27个函数.其中3个和打印驱动相关,其余24个和显示驱动相关.
GPE类可以作为开发新显示驱动的基类,GPE处理与DDI的通信和进行默认的绘图,使用GPE可以减少开发时间和调试工作量.
SMDK2410 BSP中就是实现了一个GPE的继承类S3C2410DISP.
Windows CE的驱动分层架构如下.

2.注册表设置
通过如下的设置:
IF BSP_NODISPLAY !
[HKEY_LOCAL_MACHINE/Drivers/Display/S3C2410/CONFIG]
 "DisplayDll"="s3c2410x_lcd.dll"
 "LCDVirtualFrameBase"=dword:ac100000
 "LCDPhysicalFrameBase"=dword:30100000

[HKEY_LOCAL_MACHINE/System/GDI/Drivers]
    "Display"="s3c2410x_lcd.dll"
; GWES will pass this value to the LCD driver; the driver will open the
; key to which it points to read its configuration.
[HKEY_LOCAL_MACHINE/System/GDI/DisplayCandidates]
 "Candidate10"="Drivers//Display//S3C2410//CONFIG"
ENDIF BSP_NODISPLAY !
; @CESYSGEN ENDIF CE_MODULES_DISPLAY

GWES 首先检查HKEY_LOCAL_MACHINE/System/GDI/DisplayCandidates注册表项,来获取是否有驱动程序在本机上初始化,如果有GWES就会使用第一个找到的驱动实例,否则加载Ddi.dll,这也是默认的驱动名称.
还可以通过CreateDC创建第二显示驱动(如"MyDDI.dll")

3.s3c2410x_lcd.dll
我们SMDK2410 BSP中实现的设备显示驱动动态链接库就是s3c2410x_lcd.dll,关于其在GEC2410平台上的移植可以参考之前的文章:
http://blog.csdn.net/shevsten/archive/2009/12/29/5099110.aspx
s3c2410x_lcd.dll导出2个函数DrvEnableDriver和DisplayInit,见s3c2410x_lcd.def.
在s3c2410x_lcd.cpp里实现了这两个函数,
DisplayInit是LCD驱动第一个执行的函数,来从注册表获取LCD驱动实例信息,如果失败则返回false,GWES会停止LCD驱动的初始化.代码如下:
// GWES will invoke this routine once prior to making any other calls into the driver. // This routine needs to save its instance path information and return TRUE. If it // returns FALSE, GWES will abort the display initialization. BOOL APIENTRY DisplayInit(LPCTSTR pszInstance, DWORD dwNumMonitors) { DWORD dwStatus; HKEY hkDisplay; BOOL fOk = FALSE; RETAILMSG(0, (_T("SALCD2: display instance '%s', num monitors %d/r/n"), pszInstance != NULL ? pszInstance : _T("<NULL>"), dwNumMonitors)); if(pszInstance != NULL) { _tcsncpy(gszBaseInstance, pszInstance, dim(gszBaseInstance)); } // sanity check the path by making sure it exists dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, gszBaseInstance, 0, 0, &hkDisplay); if(dwStatus == ERROR_SUCCESS) { RegCloseKey(hkDisplay); fOk = TRUE; } else { RETAILMSG(0, (_T("SALCD2: DisplayInit: can't open '%s'/r/n"), gszBaseInstance)); } return fOk; }
另一个就是DrvEnableDriver,上面已经介绍过,DrvEnableDriver向GWES子系统提供了27个DDI函数指针.DrvEnableDriver函数是任何必不可少的,负责向GDI提供DDI函数指针.GDI是GWES的组成部分,它主要负责画简单的直线,矩形,圆等几何图形及实现矩形块传输和画线操作的硬件加速.DrvEnableDriver导出函数是GDI和DDI函数之间的中介桥梁.只有DrvEnableDriver函数名是不可改变的,由它负责导出的各DDI函数都只需要一个函数地址,操作系统不限制用户如何给它们命名.

DrvEnableDriver函数原型:
BOOL APIENTRY DrvEnableDriver(ULONG engineVersion, ULONG cj, DRVENABLEDATA *data,
         PENGCALLBACKS  engineCallbacks);

在SMDK2410的LCD驱动程序中,DrvEnableDriver没有做实际的工作,只是直接将全部4个参数传递给函数GPEEnableDriver,这是个微软提供的公共代码函数.
BOOL APIENTRY DrvEnableDriver(ULONG engineVersion, ULONG cj, DRVENABLEDATA *data, PENGCALLBACKS engineCallbacks) { BOOL fOk = FALSE; // make sure we know where our registry configuration is if(gszBaseInstance[0] != 0) { fOk = GPEEnableDriver(engineVersion, cj, data, engineCallbacks); } return fOk; }
GPEEnableDriver函数实现在/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/DISPLAY/GPE/ddi_if.cpp.
GPEEnableDriver函数首先保存由engineCallbacks参数传递而来的GDI回调函数指针集合.第二项主要任务是通过pded指针参数输出DDI函数指针阵列.
memcpy(pded, &pDrvFn, cj);
pDrvFn就是DRVENABLEDATA结构包含了所有的DDI函数的函数指针.结构如下:
const DRVENABLEDATA pDrvFn = { { DrvEnablePDEV }, { DrvDisablePDEV }, { DrvEnableSurface }, { DrvDisableSurface }, { DrvCreateDeviceBitmap }, { DrvDeleteDeviceBitmap }, { DrvRealizeBrush }, { DrvStrokePath }, { DrvFillPath }, { DrvPaint }, { DrvBitBlt }, { DrvCopyBits }, { DrvAnyBlt }, { DrvTransparentBlt }, { DrvSetPalette }, { DrvSetPointerShape }, { DrvMovePointer }, { DrvGetModes }, { DrvRealizeColor }, { DrvGetMasks }, { DrvUnrealizeColor }, { DrvContrastControl }, { DrvPowerHandler }, { NULL /* DrvEndDoc */ }, { NULL /* DrvStartDoc */ }, { NULL /* DrvStartPage */ }, { DrvEscape } };
具体含义为:

Function

Description

DisplayInit

Passes instance information, which allows the driver to find PCI configuration information for its device.

The PCI bus driver populates the information if the driver has a PCI template in the registry. This is the first display driver function called by GWES.

DrvAnyBlt

Performs bit block transfers, with stretching or transparency.

DrvBitBlt

Performs general bit block transfers, with clipping and masking.

Maps to the MoveToEx, Polygon, Polyline, Ellipse, Rectangle, PolyBezier, SetPixel, BitBlt, MaskBlt, Rectangle, ExtTextOut, DrawText, and ExtTextOut GDI functions.

DrvCopyBits

Sends a GDI-created print band to a printer driver.

Maps to the SetDIBitsToDevice GDI function.

DrvCreateDeviceBitmap

Creates and manages bitmap files.

DrvDeleteDeviceBitmap

Deletes a device bitmap file.

DrvDisableDriver

Notifies the display driver that the GDI no longer needs it and is ready to unload the driver.

DrvDisablePDEV

Notifies the driver that the GDI no longer needs a particular display device.

DrvDisableSurface

Notifies the driver that the GDI no longer needs a particular drawing surface.

DrvEnableDriver

Returns pointers to DDI functions to GDI. The initial entry point that is exposed by the driver. The driver exposes the second entry point if DisplayInit is implemented.

DrvEnablePDEV

Returns a PDEV structure to the GDI. A PDEV structure is a logical representation of a physical display device.

DrvEnableSurface

Creates a drawing surface and associates it with PDEV.

DrvEndDoc

Sends any control information that is needed to finish printing a document.

DrvEscape

Retrieves information from a device that is not available in a device-independent DDI. This function operates the same as with Windows NT, except that Windows CE does not support the DrvDrawEscape function.

DrvFillPath

Fills a drawing path with a brush.

Maps to the MoveToEx, Polygon, Polyline, Ellipse, Rectangle, and PolyBezier GDI functions.

DrvGetMasks

Gets the color masks for the display device's current mode.

DrvGetModes

Lists the display modes that are supported by the display device.

DrvMovePointer

Moves the pointer with a guarantee that the GDI will not interfere with the operation.

DrvPaint

Paints a specified region with a brush.

Maps to the MoveToEx, Polygon, Polyline, Ellipse, Rectangle, and PolyBezier GDI functions.

DrvPowerHandler

Called to handle POWER_UP and POWER_DOWN notifications.

DrvRealizeBrush

Creates a brush with parameters that are specified by the GDI.

DrvRealizeColor

Maps an RGB color onto the closest available color that is supported by the device.

DrvSetPalette

Sets the display device's palette.

DrvSetPointerShape

Sets the pointer to a new shape and updates the display.

DrvStartDoc

Sends any control information that is needed to start printing a document.

DrvStartPage

Sends any control information that is needed to start printing a new page.

DrvStrokePath

Renders a drawing path.

Maps to the MoveToEx, Polygon, Polyline, Ellipse, Rectangle, and PolyBezier GDI functions.

DrvStrokeAndFillPath

Maps to the MoveToEx, Polygon, Polyline, Ellipse, Rectangle, and PolyBezier GDI functions.

DrvTransparentBlt

Bit block transfer, with transparency.

DrvUnrealizeColor

Maps a color in the display device's format onto an RGB value.

 

在ddi_if.cpp中微软提供了这些的DDI函数实现代码.

需要向GWES导出DDI函数的显示设备驱动程序都必须定义宏DDI. 在source文件中你可以看到:
!IFDEF CLEARTYPE
CDEFINES=$(CDEFINES) -DDDI -DCLEARTYPE
!ELSE
CDEFINES=$(CDEFINES) -DDDI
!ENDIF

既然DDI函数都由微软实现了,那么需要用户开发的是哪些呢,就是GPE继承类(SMDK2410 BSP中就是S3C2410DISP).下一篇我们就来详细介绍这个类及其实现.

你可能感兴趣的:(Windows CE LCD显示驱动简析(1)(基于WinCE5.0 SMDK2410 BSP的LCD显示设备驱动))