• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > WinCE 5.0下鼠標鍵盤驅動分析(下)

    WinCE 5.0下鼠標鍵盤驅動分析(下)

    作者: 時間:2011-02-27 來源:網絡 收藏

    硬件之鼠標(PS/2)

    鼠標

    l The standard PS/2 mouse supports the following inputs:

    X (right/left) movement, Y (up/down) movement, left button, middle button, and right button.

    l The mouse reads these inputs at a regular frequency and updates various counters and flags to reflect movement and button states.

    l Use the same protocol as the PS/2 (AT) keyboard.

    l PS/2 鼠標和鍵盤履行一種雙向同步串行協議.

    l 計算機啟動時檢測和初始化

    驅動

    微軟的代碼的路徑:C:WINCE500PUBLICCOMMONOAKDRIVERSKEYBD

    這里先說下,OEM商如何根據自己的硬件來寫自己的鼠標鍵盤驅動。在D:WINCE500PUBLICCOMMONOAKDRIVERS目錄下的驅動代碼都是微軟提供給OEM商的。以EMULATOR 為例,這個OEM商也提供了他們自己寫的程序在這里:D:WINCE500PLATFORMEMULATORSRCDRIVERSKBDMOUSE。這里,微軟其實給了OEM商2種選擇:1 符合微軟標準的硬件,ok,你可以選擇使用微軟提供的驅動(當然,也可以不用);2 自己做的硬件,當然只能自己寫驅動(但可以一部分調用微軟提供的庫)。

    所以,對于EMULATOR的鼠標鍵盤驅動來說,實際上由下面這些源文件構成:

    0409 是United States 101 keyboard 標準

    OK.首先,讓我們來看看D:WINCE500PUBLICCOMMONOAKDRIVERSKEYBD目錄。

    這些目錄的各自作用是:

    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_MACHINEHardwareDeviceMapKEYBDDrivername 注冊表項獲得dll名,如果沒有,則用默認的名字:Keybddr.dll。然后就是裝載dll, 并且確定函數進入點是否存在。然后輸入系統調用函數KeybdDriverInitialize來一次性初始化驅動。在這個函數里,驅動在本地保存了一份輸入系統回調函數的副本以及初始化硬件和IST來處理中斷。當一個中斷信號來的時候,鍵盤驅動負責把硬件掃描碼轉換為虛擬鍵值。然后虛擬鍵值會再發送給輸入系統。輸入系統從隊列中取出按鍵事件,然后返回到驅動程序的函數KeybdDriverVKeyToUnicode中。驅動程序根據分析特定的鍵事件和虛擬鍵的狀態產生相應的字符。輸入系統把虛擬鍵值和字符發送給合適的程序。

    Layout Manager

    WinCE下的驅動從層次這角度大概可以分2種:monolithic driver 和layered driver。其實2者的區別正如他們字面意義一樣:monolithic driver單一驅動,不分層,沒有MDD和PDD之分;layered driver具有層次架構,一般都有分為MDD和PDD。這里,鼠標鍵盤驅動就是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_PowerHandler和PS2_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)INCkbdmouse.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


    linux操作系統文章專題:linux操作系統詳解(linux不再難懂)

    p2p機相關文章:p2p原理




    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 绥江县| 剑川县| 萨嘎县| 南宫市| 云安县| 鄂托克前旗| 安西县| 图们市| 荣昌县| 京山县| 延津县| 唐河县| 明水县| 玉屏| 永新县| 玛纳斯县| 望谟县| 安康市| 伊吾县| 乳山市| 安溪县| 德阳市| 改则县| 沾益县| 伊通| 诸暨市| 论坛| 安康市| 胶南市| 洛阳市| 木兰县| 林周县| 屏南县| 江川县| 永康市| 温泉县| 沂水县| 上林县| 宁明县| 洱源县| 尖扎县|