⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keypad.cpp.bak

📁 串口驱动程序
💻 BAK
📖 第 1 页 / 共 2 页
字号:
/*
 *	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 + -