转 :我见过最完整的wince驱动源码分析

这段时间一直在看wince下的键盘驱动,终于是把源代码给看懂了,基本的机构流程都已经熟悉,本来想写一个自己的总结,突然发现前人已经帮我写好了,而且

他这个是通用的例子,或许后人看起来会更加容易理解。

原文:http://www.cnblogs.com/songtitan/archive/2005/08/04/207583.html

如下:       本文通过对WinCE 5.0下的鼠标键盘驱动分析,对WinCE驱动程序设计进行了分析。欢迎大家对不对的地方指出。        

驱动

微软的代码的路径:C:/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/KEYBD

这里先说下,OEM商如何根据自己的硬件来写自己的鼠标键盘驱动。在D:/WINCE500/PUBLIC/COMMON/OAK/DRIVERS目录下的驱动代码都是微软提供给OEM商的。以EMULATOR 为例,这个OEM商也提供了他们自己写的程序在这里:D:/WINCE500/PLATFORM/EMULATOR/SRC/DRIVERS/KBDMOUSE。这里,微软其实给了OEM2种选择:1 符合微软标准的硬件,ok,你可以选择使用微软提供的驱动(当然,也可以不用);2 自己做的硬件,当然只能自己写驱动(但可以一部分调用微软提供的库)。

       所以,对于EMULATOR的鼠标键盘驱动来说,实际上由下面这些源文件构成:



0409
United States 101 keyboard 标准

 

       OK.首先,让我们来看看D:/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/KEYBD目录。

 

 

这些目录的各自作用是:

l       DEVICELAYOUTS:      键盘布局,有几种国际标准。0409是美国101键标准

l       DLL:                             产生AT扫描码和空的驱动库,这些库在sysgen阶段被连接。

l       HIDIOCTL:                   没有布局管理器时,使用该驱动

l       INPUTLANGS                输入语言,与上面的DEVICELAYOUTS一致

l       IST                                中断服务线程

l       LAYMGR                      布局管理器

l       NOP                              当硬件平台没有键盘控制器时,Stub keyboard PDD

l       PS2_8042                       PS2_8042标准的键盘控制器驱动

l       TEST                             一个简单的测试程序

l       Keybd                            一个默认的键盘驱动注册表项

l       Laymgr                         一个默认的键盘布局注册表项

 

一个简单的过程描述:

输入系统(GWES)在启动时装在键盘驱动。首先,从HKEY_LOCAL_MACHINE/Hardware/DeviceMap/KEYBD/Drivername     注册表项获得dll名,如果没有,则用默认的名字:Keybddr.dll。然后就是装载dll, 并且确定函数进入点是否存在。然后输入系统调用函数KeybdDriverInitialize来一次性初始化驱动。在这个函数里,驱动在本地保存了一份输入系统回调函数的副本以及初始化硬件和IST来处理中断。当一个中断信号来的时候,键盘驱动负责把硬件扫描码转换为虚拟键值。然后虚拟键值会再发送给输入系统。输入系统从队列中取出按键事件,然后返回到驱动程序的函数KeybdDriverVKeyToUnicode中。驱动程序根据分析特定的键事件和虚拟键的状态产生相应的字符。输入系统把虚拟键值和字符发送给合适的程序。

 

 

 

Layout Manager

       WinCE下的驱动从层次这角度大概可以分2种:monolithic driver layered driver。其实2者的区别正如他们字面意义一样:monolithic driver单一驱动,不分层,没有MDDPDD之分;layered driver具有层次架构,一般都有分为MDDPDD。这里,鼠标键盘驱动就是layered driver

       这里有一个Layout Manager的概念

 

 

 

 

 

 

 

 

l       布局管理器处理扫描码的步骤:

 

PDD接受到一个扫描码;

扫描码被送到布局管理器;

布局管理器依据当前设备的布局和事件将其转换成虚拟键值;

布局管理器依据当前设备的布局和事件将重新映射;

布局管理器设置自动重复功能,所有的键盘都将共享相同的自动重复设置;

布局管理器调用函数keybd_event发送一个或多个事件。

 

 

PDD ----Platform Dependent Driver

 

l       PDD是下层的,负责从硬件拿到扫描码(上层的是MDD,负责将扫描码转换成字符).键盘PDD是键盘驱动中与设备相关的一部分代码。键盘PDD包括初始化和电源函数。可以使用公共的ist,也可以包括自己的。当GWES初始化键盘驱动时,它初始化每一个PDD. 每个键盘PDD有一个函数返回关于该PDD的描述和函数指针。当布局管理器初始化这个PDD,键盘驱动传递PDD一个唯一的标示符。有时,多种设备能使用同样的PDD,比如2个独立的PS/2 控制器。

l       每个PDD和布局管理器在同样的DLL里。不可以在运行时加一个PDD(但可以不同的PDD之间切换!)

 

 

源代码分析

Driver Code----Kbdmouse.cpp

实现了KEYBD_PDD结构中的2个函数(函数指针)PS2_EMUL_PowerHandlerPS2_EMUL_ToggleLights

入口函数:

         PS2_EMUL_Entry()

{

*ppKeybdPdd = &PS28042Pdd;                    //设定键盘控制器是PS2 8042键盘控制器

v_pp2p = new Ps2Port;

// We always assume that there is a keyboard.

v_pp2k = new Ps2Keybd;                                //NEW一个键盘

v_pp2k -> Initialize(v_pp2p)                           //初始化键盘

v_pp2k -> IsrThreadStart();                    //键盘中断处理线程启动

if ( v_pp2p -> bMouseFound() )                      //如果有鼠标连着的话

{

  v_pp2m = new Ps2Mouse;                           //NEW一个鼠标

v_pp2m -> Initialize(v_pp2p)                          //初始化鼠标

  v_pp2m -> IsrThreadStart();                        //鼠标中断处理线程启动

}

}

      

Driver Code----ps2mouse.cpp

实现了鼠标中断处理线程,以及获取鼠标数据(x,y,滚轮)的函数。

获取鼠标的绝对位置GetHostMousePosition()

中断服务线程实现:

IsrThreadStart ->Ps2MouseIsrThread->IsrThreadProc

IsrThreadProc()

{

//查注册表,检查中断是否能使系统从休眠中醒来. KernelIoControl

。。。。。。

m_pp2p -> MouseInterruptEnable();

for ( ; ; )

{

wait_for_interrupt:

if(WaitForSingleObject(m_hevInterrupt, (cBytes == 0 ? INFINITE : IN_PACKET_TIMEOUT)) == WAIT_TIMEOUT)

{

         //确定鼠标事件和位置,READ_PORT_UCHAR

         。。。。。。

                   goto wait_for_interrupt;

}

}

 

Driver Code---- Ps2keybd.cpp

函数调用方向:IsrThreadStart ->Ps2KeybdIsrThread->IsrThreadProc

IsrThreadProc()

{

         //查注册表,检查中断是否能使系统从休眠中醒来

         dwStatus = RegOpenKeyEx();

         if (m_pp2p->WillWake()) {

                   // Ask the OAL to enable our interrupt to wake the system from suspend.

                   KernelIoContro();

         }

         m_pp2p -> KeybdInterruptEnable();

         KeybdIstLoop ()                       // KeybdIst.lib

}

 

Driver Code---- Keybdist.cpp

KeybdIstLoop()  

{

wait_for_keybd_interrupt:

    if (WaitForSingleObject(pKeybdIst->hevInterrupt, INFINITE) == WAIT_OBJECT_0)

    {

       ....

    }

    goto wait_for_keybd_interrupt;

    ErrorShow……

}

 

 

Source file

TARGETNAME=KbdXscXTMsEngUs1

DEFFILE=$(_COMMONOAKROOT)/INC/kbdmouse.def

TARGETTYPE=DYNLINK

DLLENTRY=DllMain

TARGETLIBS= /

    $(_COMMONSDKROOT)/lib/$(_CPUINDPATH)/coredll.lib /

    $(_COMMONOAKROOT)/lib/$(_CPUINDPATH)/ceddk.lib   /

    $(_TARGETPLATROOT)/lib/$(_CPUINDPATH)/drvlib.lib

 

SOURCELIBS=/

    $(_TARGETPLATROOT)/lib/$(_CPUINDPATH)/KbdmsCommon.lib   /

    $(_COMMONOAKROOT)/lib/$(_CPUINDPATH)/KeybdIst.lib     /

    $(_COMMONOAKROOT)/lib/$(_CPUINDPATH)/PS2_AT_00000409.lib   /

    $(_COMMONOAKROOT)/lib/$(_CPUINDPATH)/layoutmanager.lib   /

    $(_TARGETPLATROOT)/lib/$(_CPUINDPATH)/kbdpddlist.lib   /

    $(_COMMONOAKROOT)/lib/$(_CPUINDPATH)/InputLang_0409.lib  /

    $(_COMMONOAKROOT)/lib/$(_CPUINDPATH)/numpadrmp.lib

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值