基于Windows CE的7×3手機(jī)鍵盤驅(qū)動實(shí)現(xiàn)
4. 矩陣鍵盤驅(qū)動程序模型
分層驅(qū)動程序由兩個獨(dú)立的層組成:上層是模型設(shè)備驅(qū)動程序(MDD),映射掃描碼到虛擬鍵的編碼上,產(chǎn)生與虛擬鍵編碼相關(guān)的字符,然后打包鍵盤信息,并且將此信息輸入到系統(tǒng)信息隊列中;下層是依賴平臺的驅(qū)動程序(PDD),它將從硬件重新獲得掃描碼。設(shè)備驅(qū)動程序服務(wù)器提供的接口(DDSI)是在PDD中實(shí)現(xiàn)的函數(shù)集,并由MDD調(diào)用。由于微軟提供了所有與MDD模塊相關(guān)的源代碼,所以對這部分不用做任何改動,只需將自己的PDD模塊與MDD模塊鏈結(jié)成一個公用庫即可。下圖2是矩陣鍵盤驅(qū)動程序分層結(jié)構(gòu)模型[2]、[3]:
圖2矩陣鍵盤驅(qū)動程序分層結(jié)構(gòu)模型
DDI函數(shù)在MDD層實(shí)現(xiàn),由用戶應(yīng)用程序通過GWES子系統(tǒng)調(diào)用,鍵盤驅(qū)動的DDI函數(shù)有[4]:KeybdDriverGetInfo、 KeybdDriverSetMode、KeybdDriverPowerHandler、KeybdDriverInitializeEx、 KeybdDriverInitStates、KeybdDriverVKeyToUnicode、KeybdDriverMapVirtualKey。
DDSI函數(shù)在PDD層實(shí)現(xiàn),由MDD層調(diào)用,鍵盤驅(qū)動的DDSI函數(shù)有:KeybdPdd_PowerHandler、KeybdPdd_InitializeDriverEx、KeybdPdd_GetEventEx、DllMain。
5. 矩陣鍵盤驅(qū)動程序運(yùn)行過程
Windows CE的輸入系統(tǒng)在啟動時加載矩陣鍵盤驅(qū)動程序,其加載流程如下:當(dāng)輸入系統(tǒng)開始運(yùn)行時,輸入系統(tǒng)將從 HKEY_LOCAL_MACHINEHardwareDeviceMapKEYBDDrivername注冊鍵中獲取矩陣鍵盤驅(qū)動動態(tài)鏈接庫(DLL)的名字。如果沒有找到入口函數(shù),系統(tǒng)將使用默認(rèn)名字Keybddr.dll,然后加載這個DLL文件,并且確認(rèn)所需要的條目指針是否都存在;然后,系統(tǒng)調(diào)用PFN_KEYBD_DRIVER_INITIALIZE 函數(shù)去執(zhí)行一次初始化工作。在這個函數(shù)中,模型設(shè)備驅(qū)動程序(MDD)存儲一個輸入系統(tǒng)回調(diào)函數(shù)的拷貝,并且處理鍵盤中斷的中斷服務(wù)線程(IST)。當(dāng)一個中斷信號發(fā)出時,鍵盤驅(qū)動將與轉(zhuǎn)變硬件掃描碼為虛擬按鍵碼有關(guān),并且與回調(diào)PFN_KEYBD_DRIVER_INITIALIZE_EX函數(shù)和 keybd_event API 有關(guān)[3]。
在CAYMAN開發(fā)板中,鍵盤驅(qū)動的動態(tài)鏈接庫名字為KeyPad.dll,入口點(diǎn)為DllMain。通過入口函數(shù),調(diào)用 KPControl::Initialize函數(shù)完成鍵盤時鐘、相關(guān)GPIO口和鍵盤中斷的一次性初始化。MDD還調(diào)用 KeyPdd_InitializeDriverEx函數(shù),該函數(shù)啟動一個線程處理鍵盤中斷,然后返回到輸入系統(tǒng)。
在CAYMAN開發(fā)板中,鍵盤驅(qū)動程序的中斷服務(wù)線程(IST)的名字是m_hevInterrupt。這個線程調(diào)用函數(shù) InterruptInitialize注冊SYSINTR_KEYBOARD中斷,然后等待系統(tǒng)發(fā)出SYSINTR_KEYBOARD信號。系統(tǒng)在收到中斷信號后,中斷處理程序調(diào)用KeypdPdd_GetEventEx函數(shù)來獲取按鍵的掃描碼,然后調(diào)用ScanCodeToVKeyEx函數(shù)將掃描碼映射成虛擬碼。把從PDD返回的鍵盤事件發(fā)送到輸入系統(tǒng),輸入系統(tǒng)對它們進(jìn)行排隊并分發(fā)給相應(yīng)的應(yīng)用程序。
6. KeypdPdd_GetEventEx函數(shù)
當(dāng)輸入系統(tǒng)載入矩陣鍵盤驅(qū)動后,由矩陣鍵盤驅(qū)動執(zhí)行一系列初始化工作,然后開啟一個線程進(jìn)入鍵盤中斷主循環(huán),等待鍵盤事件的發(fā)生。一旦發(fā)生鍵盤事件,即檢測到有按鍵被按下,立即調(diào)用KeypdPdd_GetEventEx函數(shù)來獲取按鍵的掃描碼。
其中,列為矩陣掃描輸入端,行為矩陣鍵盤輸出端,當(dāng)有按鍵被按下時,矩陣鍵盤的相應(yīng)行和列所對應(yīng)的輸入輸出電平將相應(yīng)地發(fā)生變化,通過矩陣鍵盤的掃描,將此值存儲于鍵盤接口自動掃描寄存器的相應(yīng)位中,然后將此數(shù)據(jù)進(jìn)行如下操作:
1) 屏蔽鍵盤自動掃描寄存器的列數(shù)據(jù)的值,將此值存儲于C中。
1) 屏蔽鍵盤自動掃描寄存器的行數(shù)據(jù)的值,將此值存儲于R中。
2) 將上面兩步產(chǎn)生的數(shù)據(jù)進(jìn)行或運(yùn)算,所得的數(shù)據(jù)就是被按下鍵的掃描碼。
評論