WINCE键盘驱动流程不完全分析(转载)

键盘驱动有点繁杂,可以配合以下资料查阅:

1.    Platform. Build自带的帮助文件.

2.    阅读源代码:

2.1 C:"WINCE420"Public"common"oak"drivers"keybd

2.2 C:"WINCE420"Platform"smdk2410"drivers"keybd

3.    网上的一些相关资料

 

初步查阅后可以知道,键盘驱动是分层(Layered Driver)的,上面的第2.1可以理解为MDD,2.2是我们要实现的PDD层。

 

看下面这段(:网上摘的):

一个简单的过程描述:输入系统(GWES)在启动时装在键盘驱动。首先,从HKEY_LOCAL_MACHINE"Hardware"DeviceMap"KEYBD"Drivername注册表项获得dll名,如果没有,则用默认的名字:Keybddr.dll。然后就是装载dll,并且确定函数进入点是否存在。然后输入系统调用函数KeybdDriverInitialize来一次性初始化驱动。在这个函数里,驱动在本地保存了一份输入系统回调函数的副本以及初始化硬件和IST来处理中断。当一个中断信号来的时候,键盘驱动负责把硬件扫描码转换为虚拟键值。然后虚拟键值会再发送给输入系统。输入系统从队列中取出按键事件,然后返回到驱动程序的函数KeybdDriverVKeyToUnicode中。驱动程序根据分析特定的键事件和虚拟键的状态产生相应的字符。输入系统把虚拟键值和字符发送给合适的程序。
Layout Manager
WinCE
下的驱动从层次这角度大概可以分2种:monolithic driverlayered driver。其实2者的区别正如他们字面意义一样:monolithic driver单一驱动,不分层,没有MDDPDD之分;layered driver具有层次架构,一般都有分为MDDPDD。这里,鼠标键盘驱动就是layered driver
这里有一个Layout Manager的概念


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

PDD接受到一个扫描码;扫描码被送到布局管理器;布局管理器依据当前设备的布局和事件将其转换成虚拟键值;布局管理器依据当前设备的布局和事件将重新映射;布局管理器设置自动重复功能,所有的键盘都将共享相同的自动重复设置;

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

按照顺序看一下这个KeybdDriverInitializeEx()函数,它在我的电脑中位于C:"Wince420"public"common"oak"drivers"keybd"Laymgr"laymgr.cpp文件,这个函数功能主要是:

1.创建几个事件,注意下面两个:   
g_hevBeginEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
g_hevEndEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
然后创建两个线程:
   g_hEventThread = CreateThread(NULL, 0, KeybdEventThreadProc, NULL, 0, NULL);
注意这个线程函数KeybdEventThreadProc,功能是等待上面创建的g_hevBeginEvent事件,然后调用ScanCodeToVKey得到虚拟键值(这个函数是调用我们的PDD实现的DEVICE_LAYOUT,这是什么呢,可以简单理解为扫描码到虚拟键值的对应数组:ScanCodeToVKeyTable它位于C:"Wince420"platform"smdk2410"drivers"keybd"matrix_0409"s3c2410.cpp),ScanCodeToVKey调用后,再调用SendRemappedEvent(这个函数是再次map虚拟键值->CallDLRemapFn->MatrixUsRemapVKey(这个函数位置同ScanCodeToVKeyTable数组的文件),使得我们有机会再次映射一些功能键Fn,为什么这么做?往往Matrix键盘按键不会太多,大多功能复用!)然后执行keybd_event()API函数,KeybdEventThreadProc的功能分析完成。执行时机是g_hevBeginEvent事件被触发,记住了,下面会分析到。

2.KeybdDriverInitializeEx接下来初始化每个键盘驱动PDD,PDD数组位于c:"wince420"platform"smdk2410"drivers"keybd"pddlist"pddlist.cpp:
PFN_KEYBD_PDD_ENTRY g_rgpfnPddEntries[] = {
   PS2_NOP_Entry,
   Matrix_Entry,
   NULL
};


我们关心的是Matrix_Entry,这是个函数,位于C:"wince420"platform"smdk2410"drivers"keybd"kbdcommon"kbd.cpp
BOOL WINAPI Matrix_Entry(
   UINT uiPddId,
   PFN_KEYBD_EVENT pfnKeybdEvent,
   PKEYBD_PDD *ppKeybdPdd
   )
这个函数功能就是初始目标平台硬件了,具体可以查看源代码,请注意这里的形参pfnKeybdEvent,它很重要,以致于要保存到全局变量,供之后的PDD其它函数调用。下面还会提到,记住这个全局变量是:v_pfnKeybdEvent.由于KeybdDriverInitializeEx是以KeybdEventCallback函数为参数调用这个Matrix_Entry的,所以v_pfnKeybdEvent = KeybdEventCallback.

4.    之后KeybdDriverInitializeEx函数设置输入语言与Device Layout,这里可以理解为设置键盘布局,键盘布局不同,同一个Virtual Key代表的字符不同。比如我们常用的0409语言布键盘数字8的上档键是”*”,0411日本数字8的上档键是”(”,下面会讲到如何更改键盘布局。

 

好了,下面我们换一个角度来看键盘驱动流程,从键盘中断开始:
在初始化的时候调用Matrix_Entry函数,在这个函数内部初始化硬件信息:
v_pp2k = new Ps2Keybd;
   if (v_pp2k->Initialize()) {
       v_pp2k ->IsrThreadStart();
   }
   else {
       ERRORMSG(1,(TEXT("Could not initialize ps2 keyboard."r"n")));
       delete v_pp2k;
       v_pp2k = NULL;
   }
     if (!KeybdDriverInitializeAddresses()) {
          goto leave;
     }
     v_pp2k->KeybdPowerOn();
….
这些函数在kbd.cpps3c2410kbd.cpp,初始化硬件管脚、中断等。进入IsrThreadStart->KeybdIstLoop等待键盘中断。这里的KeybdIstLoop函数参数,是个结构体,注意最后两个域:
keybdIst.pfnGetKeybdEvent = KeybdPdd_GetEventEx2;
keybdIst.pfnKeybdEvent = v_pfnKeybdEvent;
KeybdIstLoop
位于C:"wince420"public"common"oak"drivers"keybd"ist"keybdist.cpp,就是等待键盘中断,然后依次调用上面的KeybdPdd_GetEventEx2v_pfnKeybdEvent,由上面分析可知v_pfnKeybdEvent是指向KeybdEventCallback的函数指针.

KeybdPdd_GetEventEx2函数是从硬件获取键盘扫描码后转换成ScanCodeToVKeyTable数组的下标.所以,这里要做的工作即是将扫描码与虚拟键对应起来,注意这里ScanCodeToVKeyTable数组里的值是虚拟键,但不是字符,比如你可以将一个扫描码与’A’对应,但不能与’a’对应。

keybdEventCallbac()函数设置g_hevBeginEvent事件,结合上面的分析KeybdEventThreadProc()函数等待这个事件后,进行扫描码到虚拟键值的转换,最后执行keybd_event()API函数。这里就回到了上面分析的内容了。

我的分析到这里就暂时结束了,事实上还有流程没有跟完,键盘驱动尚未结束,后续的大致是根据键盘状态与键盘布局将虚拟键转成字符。如果你的键盘很简单,只有一些数字或常用字母,需要更改的不多。

 

 

posted on 2009-03-31 14:46  呼风唤雨  阅读(787)  评论(0编辑  收藏  举报

导航