📄 keypad.cpp.bak
字号:
/*
* Copyright (C) 2003 , Motorola Inc. All Rights Reserved
*
* File: drivers/keypad/Keypad.cpp
* Purpose: Hardware dependent IOControl routines for the Keypad Driver
*
* Notes:
*
* Author: Wang Hua
* Date: 08/29/2003
*
* Modifications:
* MM/DD/YYYY Initials Change Description
*/
/*********************************************************************
INCLUDE FILES
*********************************************************************/
#include <windows.h>
#include <windev.h>
#include <winbase.h>
#include <winuser.h>
#include <winuserm.h>
#include <nkIntr.h>
#include <pm.h>
#include <string.h>
#include "typesDef.h"
#include "tahiti.h"
#include "oemioctl.h"
#include "oalintr.h"
#include "pmu.h"
#include "keypad.h"
#include "keypad_map.h"
/*********************************************************************
GLOBAL DEFINITIONS
*********************************************************************/
#define KEY_DEBUG_MSG 0 //the Debug value
#define KEY_ERROR_MSG 0
#if 0
#define KPP_REPEAT_PERIOD 500 //repeat for every 500 millisecond
#define KPP_POWER_BUTTON_INDEX (KPP_POWER_COL*KPP_ROW_INUSE+KPP_POWER_ROW)
#endif
#define KEY_DEBOUNCE_PERIOD 80 // msec
/*********************************************************************
GLOBAL OR STATIC VARIABLES
*********************************************************************/
static pKppReg_t gpKpp = NULL;
static PmuClass *gpKppPmuClass = (PmuClass *) NULL;
static HANDLE ghIntrEvent = NULL;
static HANDLE ghIntrThread = NULL;
static UINT8 keyDown[KPP_COLUMN_INUSE];
static BOOL KppSuspend = FALSE;
static CRITICAL_SECTION ghKppLock;
/*********************************************************************
STATIC FUNCTION PROTOTYPES
*********************************************************************/
static void kppHandleWakeKeys(UINT8 *wakeKeys);
/*********************************************************************
EXPORTED FUNCTIONS
*********************************************************************/
/***********************************************************************
*
* FUNCTION: Key_IntrThread
*
* DESCRIPTION: This function is a interrupt thread
* to handle keypad interrupts
*
* NOTE:
*
* PARAMETERS:
*
* RETURNS:
* A double word value for ExitThread()
*
**********************************************************************/
DWORD WINAPI KEY_IntrThread(LPVOID lpParameter) //中断处理函数,该函数在初始化后调用line447
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_IntrThread+\r\n")));
static UINT8 kppStatus[KPP_COLUMN_INUSE];
UINT8 wakeKeys[KPP_COLUMN_INUSE];
static UINT32 prevDownTime;
DWORD dwSources;
DWORD dwTransferred;
UINT16 tempKPSR;
UINT8 iRowMask;
UINT8 iColMask;
UINT8 iCol;
UINT8 iRow;
UINT8 index;
UINT8 rowData;
// Initialise key status to all release '1' and clear key down status.
KEY_DEBUG_MSG(kppStatus, KPP_ROW_MASK, sizeof(kppStatus));
memset(keyDown, 0, sizeof(keyDown));
prevDownTime = 0;
// Ask OAL to enable KPP interrupt to wake system from suspend.
// Also register function with OAL for checking of valid wake keys
dwSources = SYSINTR_KPP; //中断?
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_IntrThread: IOCTL_HAL_ENABLE_WAKE\r\n")));
KernelIoControl(IOCTL_HAL_ENABLE_WAKE, &dwSources, sizeof(DWORD),
NULL, 0, &dwTransferred); //使用该函数取得中断唤醒
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_IntrThread: IOCTL_HAL_SET_WAKE_KEYS\r\n")));
KernelIoControl(IOCTL_HAL_SET_WAKE_KEYS, WakeKeyMap, sizeof(WakeKeyMap),
NULL, 0, &dwTransferred); //设置唤醒键
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_IntrThread: IOCTL_HAL_SET_WAKE_CHECK\r\n")));
KernelIoControl(IOCTL_HAL_ENABLE_WAKE_CHECK, &dwSources, sizeof(DWORD),
NULL, 0, &dwTransferred); //再次使用该函数,进行检查
while(TRUE)
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_IntrThread: WaitForSingleObject:\r\n")));
if(WaitForSingleObject(ghIntrEvent, INFINITE) != WAIT_OBJECT_0)
{
// Should NEVER come here!
ERRORMSG(1, (TEXT("KEY_IntrThread: WaitForSingleObject Timeout!\r\n")));
continue;
}
EnterCriticalSection(&ghKppLock); //执行该区域的代码
// Read keypad status register,将键盘状态读出
tempKPSR = gpKpp->KPSR;
// Disable interrupts while processing. ,将中断都屏蔽掉
gpKpp->KPSR &= ~(bmKPSR_KDIE | bmKPSR_KRIE);
if(GET_BOOL(tempKPSR, KPSR_KPKD) && GET_BOOL(tempKPSR, KPSR_KDIE))
{
// At least 1 key depressed
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("Depress interrupt, KPSR 0x%04x. \r\n"), tempKPSR));
// Write '1' to all columns
SET_BITS(gpKpp->KPDR, KPDR_KCD, KPP_COLUMN_MASK);
// Configure column as totem-pole outputs
SET_BITS(gpKpp->KPCR, KPCR_KCO, ~KPP_COLUMN_MASK);
// Scan key map for changes
for(iCol = 0, iColMask = 1; iCol < KPP_COLUMN_INUSE; iCol++, iColMask <<= 1)
{
// Write '0' for this column.
SET_BITS(gpKpp->KPDR, KPDR_KCD, ~iColMask);
Sleep(1);
// Get current key status & handle accordingly
rowData = KPP_ROW_MASK & GET_BITS(gpKpp->KPDR, KPDR_KRD);
for(iRow = 0, iRowMask = 1; iRow < KPP_ROW_INUSE; iRow++, iRowMask <<= 1)
{
if((rowData & iRowMask) ^ (kppStatus[iCol] & iRowMask))
{
// Key status changed. Send event accordingly.
index = iCol * KPP_ROW_INUSE + iRow;
if((rowData & iRowMask))
{
// Key status changed to released.
// Handle briefly pressed non power keys.
if(index != KPP_POWER_BUTTON_INDEX)
{
if(!(kppStatus[iCol] & iRowMask) && !(keyDown[iCol] & iRowMask))
{
// Key depressed very briefly, less than 1 debounce period.
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("Changed: depressed < 1 period.\r\n")));
if(ExtraKeyCodeSequenceTable[index] != 0)
keybd_event(ExtraKeyCodeSequenceTable[index], index, 0, 0);
keybd_event(KeyCodeSequenceTable[index], index, 0, 0); //该表在keypad_map.h中定义
}
keybd_event(KeyCodeSequenceTable[index], index, KEYEVENTF_KEYUP, 0);
if(ExtraKeyCodeSequenceTable[index] != 0)
keybd_event(ExtraKeyCodeSequenceTable[index], index, KEYEVENTF_KEYUP, 0);
keyDown[iCol] &= ~iRowMask;
}
}
else
{
// Key status changed to depressed.
if(index == KPP_POWER_BUTTON_INDEX)
{
keyDown[iCol] |= iRowMask;
}
prevDownTime = GetTickCount();
}
}
else // No key status change
{
if(!(rowData & iRowMask))
{
// Key still depressed.
// Send key down event after debouncing period.
if(GetTickCount() < prevDownTime)
prevDownTime = 0;
if( (GetTickCount() - prevDownTime) >= KEY_DEBOUNCE_PERIOD)
{
index = iCol * KPP_ROW_INUSE + iRow;
if(!(keyDown[iCol] & iRowMask))
keyDown[iCol] |= iRowMask;
if(index != KPP_POWER_BUTTON_INDEX)
{
// Non power key handling
if(ExtraKeyCodeSequenceTable[index] != 0)
keybd_event(ExtraKeyCodeSequenceTable[index], index, 0, 0);
keybd_event(KeyCodeSequenceTable[index], index, 0, 0);
}
prevDownTime = GetTickCount();
}
}
}
}
// Store current keypad status
kppStatus[iCol] = rowData;
}
// Done keypad scanning.
SET_BITS(gpKpp->KPDR, KPDR_KCD, ~KPP_COLUMN_MASK);
SET_BITS(gpKpp->KPCR, KPCR_KCO, KPP_COLUMN_MASK);
// Power key down handling. Note: power key takes precedence.
// Ignore power key down if just back from suspend.
if(keyDown[KPP_POWER_COL] & (1 << KPP_POWER_ROW))
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("Power key down!\r\n")));
if(!KppSuspend)
{
// Configure to enable wake up keys only.
KppSuspend = TRUE;
// Configure keypad to check for power key only
SET_2BITS(gpKpp->KPCR, KPCR_KCO, (1 << KPP_POWER_COL), KPCR_KRE, (1 << KPP_POWER_ROW));
SET_2BITS(gpKpp->KDDR, KDDR_KCDD, (1 << KPP_POWER_COL), KDDR_KRDD, ~(1 << KPP_POWER_ROW));
gpKpp->KPSR |= (bmKPSR_KDIE | bmKPSR_KPKD | bmKPSR_KPKR | bmKPSR_KDSC | bmKPSR_KRSS);
// Sleep while waiting for all keys to be released before
// suspending the system.
gpKpp->KPSR |= (bmKPSR_KPKR | bmKPSR_KRSS);
while(!(gpKpp->KPSR & bmKPSR_KPKR))
Sleep(KEY_DEBOUNCE_PERIOD);
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("Sending Power key!\r\n")));
SetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("Key suspend returned!\r\n")));
}
}
else
{
// Re-enable interrupts.完成服务后,恢复中断使能
gpKpp->KPSR |= (bmKPSR_KRSS | bmKPSR_KPKR | bmKPSR_KPKD | bmKPSR_KDSC |
bmKPSR_KDIE | bmKPSR_KRIE);
}
}
else if(GET_BOOL(tempKPSR, KPSR_KPKR) && GET_BOOL(tempKPSR, KPSR_KRIE))
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("Release interrupt, KPSR 0x%04x. \r\n"), tempKPSR));
// All configured keys released. Reset all key indicators
// and send key up event for all keys marked as down.
for(iCol = 0; iCol < KPP_COLUMN_INUSE; iCol++)
{
for(iRow = 0, iRowMask = 1; iRow < KPP_ROW_INUSE; iRow++, iRowMask <<= 1)
{
index = iCol * KPP_ROW_INUSE + iRow;
if(keyDown[iCol] & iRowMask)
{
// Handle keys marked as down.
keybd_event(KeyCodeSequenceTable[index], index, KEYEVENTF_KEYUP, 0);
if(ExtraKeyCodeSequenceTable[index] != 0)
keybd_event(ExtraKeyCodeSequenceTable[index], index, KEYEVENTF_KEYUP, 0);
if(index == KPP_POWER_BUTTON_INDEX)
{
KppSuspend = FALSE;
SetSystemPowerState(NULL, POWER_STATE_ON, 0);
// Handle wake keys
dwSources = SYSWAKE_UNKNOWN;
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("IOCTL_HAL_GET_WAKE_SOURCE\r\n")));
KernelIoControl(IOCTL_HAL_GET_WAKE_SOURCE, NULL, 0,
&dwSources, sizeof(DWORD), &dwTransferred);
if(dwSources == SYSINTR_KPP)
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("IOCTL_HAL_GET_WAKE_KEYS\r\n")));
KernelIoControl(IOCTL_HAL_GET_WAKE_KEYS, NULL, 0,
&wakeKeys, sizeof(wakeKeys), &dwTransferred);
if(dwTransferred == sizeof(wakeKeys))
kppHandleWakeKeys(wakeKeys);
}
}
}
else
{
// Take care of non power keys that are depressed only very briefly.
if(index != KPP_POWER_BUTTON_INDEX)
{
if(!(kppStatus[iCol] & iRowMask))
{
// Key depressed very briefly, less than 1 debounce period.
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("keys depressed for less than 1 period.\r\n")));
if(ExtraKeyCodeSequenceTable[index] != 0)
keybd_event(ExtraKeyCodeSequenceTable[index], index, 0, 0);
keybd_event(KeyCodeSequenceTable[index], index, 0, 0);
}
keybd_event(KeyCodeSequenceTable[index], index, KEYEVENTF_KEYUP, 0);
if(ExtraKeyCodeSequenceTable[index] != 0)
keybd_event(ExtraKeyCodeSequenceTable[index], index, KEYEVENTF_KEYUP, 0);
}
}
}
// Clear indicators.
keyDown[iCol] = ~KPP_ROW_MASK;
kppStatus[iCol] = KPP_ROW_MASK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -