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

📄 kbdist.cpp

📁 三星2410的BSP开发包
💻 CPP
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

	@doc	EXTERNAL DRIVERS

	@module	keybdist.cpp |

This file implements the interrupt service thread part of the platform
independent code of the keyboard driver.  This is provided as a sample to
platform driver writers and is expected to be able to be used without
major modification on most hardware platforms.

*/

#include <windows.h>
#include <nkintr.h>
#include <keybddr.h>
#include <keybdpdd.h>

//	Auto repeat #defines and state variables.
#define AR_WAIT_FOR_ANY		0
#define AR_INITIAL_DELAY	1
#define AR_AUTOREPEATING	2
#define AR_AUTO_PARTIAL     3   // Auto repeat was interrupted by real PDD event.

#define AUTO_REPEAT_INITIAL_DELAY_MIN		250
#define AUTO_REPEAT_INITIAL_DELAY_MAX		1000
#define AUTO_REPEAT_INITIAL_DELAY_DEFAULT	500

#define AUTO_REPEAT_KEYS_PER_SEC_MIN		2
#define AUTO_REPEAT_KEYS_PER_SEC_MAX		30
#define AUTO_REPEAT_KEYS_PER_SEC_DEFAULT	20

static int				v_AutoRepeatState = AR_WAIT_FOR_ANY;
static DWORD			v_AutoRepeatInitialDelay = AUTO_REPEAT_INITIAL_DELAY_DEFAULT;
static DWORD			v_AutoRepeatKeysPerSec = AUTO_REPEAT_KEYS_PER_SEC_DEFAULT;
static UINT32			v_AutoRepeatVKey;
static UINT32			v_AutoRepeatScanCode;
static KEY_STATE_FLAGS	v_AutoRepeatKeyStateFlags;

extern DWORD dwSysIntr_Keybd;

//	Routine to call back in to user when there is a keyboard event.
static PFN_KEYBD_EVENT_CALLBACK_EX	v_pfnKeybdEventCallbackEx;

extern "C"
//      @doc EXTERNAL DRIVERS
/*      @func

Gives information about the keyboard and driver.


@rdesc If the function succeeds the return value is TRUE, otherwise, it is
FALSE.  Extended error information is available via the GetLastError
function.

@xref
	<tab><c KBDI_VKEY_TO_UNICODE_INFO_ID><nl>
	<tab><c KBDI_AUTOREPEAT_INFO_ID><nl>
	<tab><c KBDI_AUTOREPEAT_SELECTIONS_INFO_ID>

@comm This function must be re-entrant since it is exposed by the input
system via the <f KeybdGetDeviceInfo> function and may be called by
multiple threads.

*/
BOOL KeybdDriverGetInfo(
	INT		iKeybdId,	// @parm Id of the keyboard to get the information from.
	INT		iIndex,		// @parm Id of info to retrieve.
	LPVOID  lpOutput	// @parm Output buffer.
	)
{
	if ( lpOutput == NULL )
		{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
		}

	switch ( iIndex )
		{
		case KBDI_VKEY_TO_UNICODE_INFO_ID:
			VKeyToUnicodeInfo((struct KBDI_VKEY_TO_UNICODE_INFO*)lpOutput);
			break;

		case KBDI_AUTOREPEAT_INFO_ID:
			{
			struct KBDI_AUTOREPEAT_INFO	*pInfo =
					(struct KBDI_AUTOREPEAT_INFO*)lpOutput;
			pInfo -> CurrentInitialDelay = v_AutoRepeatInitialDelay;
			pInfo -> CurrentRepeatRate = v_AutoRepeatKeysPerSec;
			pInfo -> cInitialDelaysSelectable = -1;
			pInfo -> cRepeatRatesSelectable = -1;
			}
			break;

		case KBDI_AUTOREPEAT_SELECTIONS_INFO_ID:
			{
			INT32	*pInfo = (INT32*)lpOutput;
			*(pInfo)	= AUTO_REPEAT_INITIAL_DELAY_MIN;		//	Min initial delay
			*(pInfo+1)	= AUTO_REPEAT_INITIAL_DELAY_MAX;		//	Max initial delay
			*(pInfo+2)	= AUTO_REPEAT_KEYS_PER_SEC_MIN;		//	Min repeat rate
			*(pInfo+3)	= AUTO_REPEAT_KEYS_PER_SEC_MAX;		//	Max repeat rate
			}
			break;

		default:
			SetLastError(ERROR_INVALID_PARAMETER);
			return FALSE;
		}
  return TRUE;
}
#ifdef DEBUG
PFN_KEYBD_DRIVER_GET_INFO v_pfnGetInfoTest = KeybdDriverGetInfo;
#endif








extern "C"
//      @doc EXTERNAL DRIVERS
/*		@func

Sets information about the keyboard device.

@rdesc If the function succeeds the return value is TRUE, otherwise, it is
FALSE.  Extended error information is available via the GetLastError
function.

@xref
	<tab><f KeybdDriverGetIno><nl>
	<tab><c KBDI_AUTOREPEAT_INFO_ID><nl>

--*/
BOOL KeybdDriverSetMode(
	INT		iKeybdId,	// @parm Id of the keyboard to set the information.
	INT		iIndex,		// @parm Id of info to set.
	LPVOID	lpInput 	// @parm Input buffer.
    )
{
	if ( lpInput == NULL )
		{
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
		}

	switch ( iIndex )
		{
		case KBDI_AUTOREPEAT_INFO_ID:
			{
			struct KBDI_AUTOREPEAT_INFO	*pInfo =
					(struct KBDI_AUTOREPEAT_INFO*)lpInput;
			if ( pInfo -> CurrentInitialDelay > AUTO_REPEAT_INITIAL_DELAY_MAX )
				{
//				RETAILMSG(1,
//					(TEXT("Initial delay too large, using %d\r\n"),
//						AUTO_REPEAT_INITIAL_DELAY_MAX));
				v_AutoRepeatInitialDelay = AUTO_REPEAT_INITIAL_DELAY_MAX;
				}
			else if ( pInfo -> CurrentInitialDelay < AUTO_REPEAT_INITIAL_DELAY_MIN )
				{
//				RETAILMSG(1,
//					(TEXT("Initial delay too small, using %d\r\n"),
//						AUTO_REPEAT_INITIAL_DELAY_MIN));
				v_AutoRepeatInitialDelay = AUTO_REPEAT_INITIAL_DELAY_MIN;
				}
			else
				{
				v_AutoRepeatInitialDelay = pInfo -> CurrentInitialDelay;
				}


			if ( pInfo -> CurrentRepeatRate > AUTO_REPEAT_KEYS_PER_SEC_MAX )
				{
//				RETAILMSG(1,
//					(TEXT("Initial repeat rate too large, using %d\r\n"),
//						AUTO_REPEAT_KEYS_PER_SEC_MAX));
				v_AutoRepeatKeysPerSec = AUTO_REPEAT_KEYS_PER_SEC_MAX;
				}
			else if ( ( pInfo -> CurrentRepeatRate < AUTO_REPEAT_KEYS_PER_SEC_MIN ) &&
					  ( pInfo -> CurrentRepeatRate != 0 ) )
				{
//				RETAILMSG(1,
//					(TEXT("Initial repeat rate too small, using %d\r\n"),
//						AUTO_REPEAT_KEYS_PER_SEC_MIN));
				v_AutoRepeatKeysPerSec = AUTO_REPEAT_KEYS_PER_SEC_MIN;
				}
			else
				{
				v_AutoRepeatKeysPerSec = pInfo -> CurrentRepeatRate;
				}

			}
			break;

		default:
			SetLastError(ERROR_INVALID_PARAMETER);
			return FALSE;
		}

	return TRUE;
}
#ifdef DEBUG
PFN_KEYBD_DRIVER_SET_MODE  v_pfnSetModeTest = KeybdDriverSetMode;
#endif

/*++

KeybdDriverThread:

Keyboard driver interrupt service thread.


Return Value:

Never returns.

--*/
BOOL
KeybdIstLoop(
	HANDLE	hevInterrupt
	)
{
	UINT32			VKeyBuf[16];			//	hardcoded w/ PDD.
	UINT32			ScanCodeBuf[16];		//	hardcoded w/ PDD.
	KEY_STATE_FLAGS	KeyStateFlagsBuf[16];	//  hardcoded w/ PDD.

	UINT32			RemapVKeyBuf[16];
	UINT32			RemapScanCodeBuf[16];
	KEY_STATE_FLAGS	RemapKeyStateFlagsBuf[16];

	int				cKeyEvents;
	int				iKeyEventIdx;

	int				cRemapEvents;
	int				iRemapIdx;

	DWORD			AutoRepeatKeysPerSec;
	long			AutoRepeatTimeout;
	BOOL			fSendAutoRepeatKey;
	DWORD			MRKeyTimeForPolling = 0;	//Get rid of compiler uninitialized variable warning.

    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

	AutoRepeatTimeout = INFINITE;

wait_for_keybd_interrupt:
    fSendAutoRepeatKey = FALSE;

//	Grab a copy once w/o critical section.
	AutoRepeatKeysPerSec = v_AutoRepeatKeysPerSec;

//	0 keys per second => auto repeat disabled.
	if ( AutoRepeatKeysPerSec == 0 )
		v_AutoRepeatState = AR_WAIT_FOR_ANY;

	if ( v_AutoRepeatState == AR_WAIT_FOR_ANY )
		{
		AutoRepeatTimeout = INFINITE;
		}
	else if ( v_AutoRepeatState == AR_INITIAL_DELAY )
		{
		AutoRepeatTimeout = v_AutoRepeatInitialDelay;
		}
	else if ( v_AutoRepeatState == AR_AUTO_PARTIAL )
		{
        long lTemp = AutoRepeatTimeout - (GetTickCount() - MRKeyTimeForPolling);
        AutoRepeatTimeout = (lTemp > 0) ? lTemp : 0;
		}
	else
		{
		AutoRepeatTimeout = 1000/AutoRepeatKeysPerSec;
		}

    MRKeyTimeForPolling = GetTickCount();
	if ( WaitForSingleObject(hevInterrupt, AutoRepeatTimeout) == WAIT_TIMEOUT )
		{

/*	On power off, the v_AutoRepeatState is set to AR_WAIT_FOR_ANY, but we
cannot reset the WaitForSingleObject timeout value.  This means that when
we power on, we could (and probably will) come back from the wait with a
wait timeout status.  In this case, we do nothing and come back around to
wait again with the proper timeout.  */
	
		if ( v_AutoRepeatState == AR_WAIT_FOR_ANY )
			;	//	do nothing
		else if ( v_AutoRepeatState == AR_INITIAL_DELAY )
			{
			fSendAutoRepeatKey = TRUE;
			v_AutoRepeatState = AR_AUTOREPEATING;
			}
		else if ( v_AutoRepeatState == AR_AUTO_PARTIAL )
			{
			fSendAutoRepeatKey = TRUE;
			v_AutoRepeatState = AR_AUTOREPEATING;
			}
		else
			{
			fSendAutoRepeatKey = TRUE;
			}
		}
	else
		{
		//	We got a keyboard interrupt but there may or may not be key events.
		cKeyEvents = KeybdPdd_GetEventEx(VKeyBuf, ScanCodeBuf, KeyStateFlagsBuf);
		if ( cKeyEvents )
			{
			for ( iKeyEventIdx = 0; iKeyEventIdx < cKeyEvents; iKeyEventIdx++ )
				{
				if ( KeyStateIsDown(KeyStateFlagsBuf[iKeyEventIdx]) )
					{
					MRKeyTimeForPolling = GetTickCount();
					v_AutoRepeatState = AR_INITIAL_DELAY;
					v_AutoRepeatVKey = VKeyBuf[iKeyEventIdx];
					v_AutoRepeatScanCode = ScanCodeBuf[iKeyEventIdx];
					v_AutoRepeatKeyStateFlags = KeyStateFlagsBuf[iKeyEventIdx];

					cRemapEvents = KeybdDriverRemapVKeyDownEx(
							VKeyBuf[iKeyEventIdx],
							ScanCodeBuf[iKeyEventIdx],
							KeyStateFlagsBuf[iKeyEventIdx],
							RemapVKeyBuf,
							RemapScanCodeBuf,
							RemapKeyStateFlagsBuf
							);

					for ( iRemapIdx = 0; iRemapIdx < cRemapEvents; iRemapIdx++ )
						{
//						RETAILMSG(1,
//							(TEXT("D %d %x %x\r\n"),
//								j, RemapVKeyBuf[j], RemapKeyStateFlagsBuf[j]));
						if ( v_pfnKeybdEventCallbackEx )
							{
							(*v_pfnKeybdEventCallbackEx)(
								RemapVKeyBuf[iRemapIdx],
								RemapScanCodeBuf[iRemapIdx],
								RemapKeyStateFlagsBuf[iRemapIdx]);
							}
						}
					}
				else
					{
					v_AutoRepeatState = AR_WAIT_FOR_ANY;

					cRemapEvents = KeybdDriverRemapVKeyUpEx(
							VKeyBuf[iKeyEventIdx],
							ScanCodeBuf[iKeyEventIdx],
							KeyStateFlagsBuf[iKeyEventIdx],
							RemapVKeyBuf,
							RemapScanCodeBuf,
							RemapKeyStateFlagsBuf
							);

					for ( iRemapIdx = 0; iRemapIdx < cRemapEvents; iRemapIdx++ )
						{
//					RETAILMSG(1, (TEXT("U %d %x %x\r\n"), j, RemapVKeyBuf[j], RemapKeyStateFlagsBuf[j]));
						if ( v_pfnKeybdEventCallbackEx )
							{
							(*v_pfnKeybdEventCallbackEx)(
								RemapVKeyBuf[iRemapIdx],
								RemapScanCodeBuf[iRemapIdx],
								RemapKeyStateFlagsBuf[iRemapIdx]);
							}
						}
					}
				}
			}
		else
			{
//	We did not get a timeout from the wait or key events.  We must be periodically polling.
//	This means that we will need to do the timing here.
			if ( ( v_AutoRepeatState == AR_INITIAL_DELAY ) ||
				 ( v_AutoRepeatState == AR_AUTO_PARTIAL ) ||
				 ( v_AutoRepeatState == AR_AUTOREPEATING ) )
				{
					v_AutoRepeatState = AR_AUTO_PARTIAL;
				}
			}
//  Ack the interrupt.
		InterruptDone(dwSysIntr_Keybd);
		}

	if ( fSendAutoRepeatKey )
		{
		cRemapEvents = KeybdDriverRemapVKeyDownEx(
							v_AutoRepeatVKey,
							v_AutoRepeatScanCode,
							v_AutoRepeatKeyStateFlags,
							RemapVKeyBuf,
							RemapScanCodeBuf,
							RemapKeyStateFlagsBuf
							);

		for ( iRemapIdx = 0; iRemapIdx < cRemapEvents; iRemapIdx++ )
			{
//			RETAILMSG(1,
//				(TEXT("D %d %x %x\r\n"),
//					j, RemapVKeyBuf[j], RemapKeyStateFlagsBuf[j]));
			if ( v_pfnKeybdEventCallbackEx )
				{
				(*v_pfnKeybdEventCallbackEx)(
					RemapVKeyBuf[iRemapIdx],
					RemapScanCodeBuf[iRemapIdx],
					RemapKeyStateFlagsBuf[iRemapIdx]);
				}
			}
		}
    
	goto wait_for_keybd_interrupt;

	ERRORMSG(1, (TEXT("Keyboard driver thread terminating.\r\n")));
	return 0;
}



extern "C"
/*++

@doc EXTERNAL DRIVERS

@func

System power state change notification.

@comm This routine is called in a kernel context and may not make any
system calls whatsoever.  It may read and write its own memory and that's
about it.

@comm Resets the auto-repeat state and calls the <f KeybdPdd_PowerHandler> routine.

--*/
void KeybdDriverPowerHandler(
	BOOL	bOff	// @parm TRUE, the system is powering off; FALSE, the system is powering up.
	)
{
	v_AutoRepeatState = AR_WAIT_FOR_ANY;
	KeybdPdd_PowerHandler(bOff);
	return;
}

#ifdef DEBUG
PFN_KEYBD_DRIVER_POWER_HANDLER v_pfnPowerHandler = KeybdDriverPowerHandler;
#endif



extern "C"
//	@doc EXTERNAL DRIVERS
/*	@func Do one time only keyboard driver initialization.

@rdesc If the function succeeds the return value is TRUE, otherwise, it is
FALSE.  Extended error information is available via the GetLastError
function.

@comm Calls <f KeybdPdd_InitializeDriver> then starts driver interrupt
service thread.

--*/
void KeybdDriverInitializeEx(
	PFN_KEYBD_EVENT_CALLBACK_EX	pfnKeybdEventCallbackEx	// @parm The callback into the input system.
	)
{
	v_pfnKeybdEventCallbackEx = pfnKeybdEventCallbackEx;

	KeybdPdd_InitializeDriverEx(pfnKeybdEventCallbackEx);

	(*pfnKeybdEventCallbackEx)(KEYBD_DEVICE_CONNECT, 0, 0);

	return;
}

#ifdef DEBUG
PFN_KEYBD_DRIVER_INITIALIZE_EX v_pfnDriverInitializeTestEx = KeybdDriverInitializeEx;
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -