audk/EmulatorPkg/Win/Host/WinGopInput.c

418 lines
11 KiB
C

/** @file
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
WinGopInput.c
Abstract:
This file produces the Simple Text In for an Gop window.
This stuff is linked at the hip to the Window, since the window
processing is done in a thread kicked off in WinNtGopImplementation.c
Since the window information is processed in an other thread we need
a keyboard Queue to pass data about. The Simple Text In code just
takes data off the Queue. The WinProc message loop takes keyboard input
and places it in the Queue.
**/
#include "WinGop.h"
/**
TODO: Add function description
@param Private TODO: add argument description
@retval EFI_SUCCESS TODO: Add description for return value
**/
EFI_STATUS
GopPrivateCreateQ (
IN GRAPHICS_PRIVATE_DATA *Private,
IN GOP_QUEUE_FIXED *Queue
)
{
InitializeCriticalSection (&Queue->Cs);
Queue->Front = 0;
Queue->Rear = 0;
return EFI_SUCCESS;
}
/**
TODO: Add function description
@param Private TODO: add argument description
@retval EFI_SUCCESS TODO: Add description for return value
**/
EFI_STATUS
GopPrivateDestroyQ (
IN GRAPHICS_PRIVATE_DATA *Private,
IN GOP_QUEUE_FIXED *Queue
)
{
Queue->Front = 0;
Queue->Rear = 0;
DeleteCriticalSection (&Queue->Cs);
return EFI_SUCCESS;
}
/**
TODO: Add function description
@param Private TODO: add argument description
@param Key TODO: add argument description
@retval EFI_NOT_READY TODO: Add description for return value
@retval EFI_SUCCESS TODO: Add description for return value
**/
EFI_STATUS
GopPrivateAddQ (
IN GRAPHICS_PRIVATE_DATA *Private,
IN GOP_QUEUE_FIXED *Queue,
IN EFI_KEY_DATA *KeyData
)
{
EnterCriticalSection (&Queue->Cs);
if ((Queue->Rear + 1) % MAX_Q == Queue->Front) {
LeaveCriticalSection (&Queue->Cs);
return EFI_NOT_READY;
}
CopyMem (&Queue->Q[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));
Queue->Rear = (Queue->Rear + 1) % MAX_Q;
LeaveCriticalSection (&Queue->Cs);
return EFI_SUCCESS;
}
/**
TODO: Add function description
@param Private TODO: add argument description
@param Key TODO: add argument description
@retval EFI_NOT_READY TODO: Add description for return value
@retval EFI_SUCCESS TODO: Add description for return value
**/
EFI_STATUS
GopPrivateDeleteQ (
IN GRAPHICS_PRIVATE_DATA *Private,
IN GOP_QUEUE_FIXED *Queue,
OUT EFI_KEY_DATA *Key
)
{
EnterCriticalSection (&Queue->Cs);
if (Queue->Front == Queue->Rear) {
LeaveCriticalSection (&Queue->Cs);
return EFI_NOT_READY;
}
CopyMem (Key, &Queue->Q[Queue->Front], sizeof (EFI_KEY_DATA));
Queue->Front = (Queue->Front + 1) % MAX_Q;
if (Key->Key.ScanCode == SCAN_NULL && Key->Key.UnicodeChar == CHAR_NULL) {
if (!Private->IsPartialKeySupport) {
//
// If partial keystrok is not enabled, don't return the partial keystroke.
//
LeaveCriticalSection (&Queue->Cs);
ZeroMem (Key, sizeof (EFI_KEY_DATA));
return EFI_NOT_READY;
}
}
LeaveCriticalSection (&Queue->Cs);
return EFI_SUCCESS;
}
/**
TODO: Add function description
@param Private TODO: add argument description
@retval EFI_NOT_READY TODO: Add description for return value
@retval EFI_SUCCESS TODO: Add description for return value
**/
EFI_STATUS
GopPrivateCheckQ (
IN GOP_QUEUE_FIXED *Queue
)
{
if (Queue->Front == Queue->Rear) {
return EFI_NOT_READY;
}
return EFI_SUCCESS;
}
/**
Initialize the key state.
@param Private The GOP_PRIVATE_DATA instance.
@param KeyState A pointer to receive the key state information.
**/
VOID
InitializeKeyState (
IN GRAPHICS_PRIVATE_DATA *Private,
IN EFI_KEY_STATE *KeyState
)
{
KeyState->KeyShiftState = EFI_SHIFT_STATE_VALID;
KeyState->KeyToggleState = EFI_TOGGLE_STATE_VALID;
//
// Record Key shift state and toggle state
//
if (Private->LeftCtrl) {
KeyState->KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
}
if (Private->RightCtrl) {
KeyState->KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
}
if (Private->LeftAlt) {
KeyState->KeyShiftState |= EFI_LEFT_ALT_PRESSED;
}
if (Private->RightAlt) {
KeyState->KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
}
if (Private->LeftShift) {
KeyState->KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
}
if (Private->RightShift) {
KeyState->KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
}
if (Private->LeftLogo) {
KeyState->KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
}
if (Private->RightLogo) {
KeyState->KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
}
if (Private->Menu) {
KeyState->KeyShiftState |= EFI_MENU_KEY_PRESSED;
}
if (Private->SysReq) {
KeyState->KeyShiftState |= EFI_SYS_REQ_PRESSED;
}
if (Private->CapsLock) {
KeyState->KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
}
if (Private->NumLock) {
KeyState->KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
}
if (Private->ScrollLock) {
KeyState->KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
}
if (Private->IsPartialKeySupport) {
KeyState->KeyToggleState |= EFI_KEY_STATE_EXPOSED;
}
}
/**
TODO: Add function description
@param Private TODO: add argument description
@param Key TODO: add argument description
@retval EFI_NOT_READY TODO: Add description for return value
@retval EFI_SUCCESS TODO: Add description for return value
**/
EFI_STATUS
GopPrivateAddKey (
IN GRAPHICS_PRIVATE_DATA *Private,
IN EFI_INPUT_KEY Key
)
{
EFI_KEY_DATA KeyData;
KeyData.Key = Key;
InitializeKeyState (Private, &KeyData.KeyState);
//
// Convert Ctrl+[1-26] to Ctrl+[A-Z]
//
if ((Private->LeftCtrl || Private->RightCtrl) &&
(KeyData.Key.UnicodeChar >= 1) && (KeyData.Key.UnicodeChar <= 26)
) {
if ((Private->LeftShift || Private->RightShift) == Private->CapsLock) {
KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar + L'a' - 1);
} else {
KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar + L'A' - 1);
}
}
//
// Unmask the Shift bit for printable char
//
if (((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) ||
((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z'))
) {
KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
}
GopPrivateAddQ (Private, &Private->QueueForRead, &KeyData);
if (Private->MakeRegisterdKeyCallback != NULL) {
Private->MakeRegisterdKeyCallback (Private->RegisterdKeyCallbackContext, &KeyData);
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
WinNtWndCheckKey (
IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo
)
{
GRAPHICS_PRIVATE_DATA *Private;
Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
return GopPrivateCheckQ (&Private->QueueForRead);
}
EFI_STATUS
EFIAPI
WinNtWndGetKey (
IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
IN EFI_KEY_DATA *KeyData
)
/*++
Routine Description:
Reads the next keystroke from the input device. The WaitForKey Event can
be used to test for existance of a keystroke via WaitForEvent () call.
Arguments:
Private - The private structure of WinNt Gop device.
KeyData - A pointer to a buffer that is filled in with the keystroke
state data for the key that was pressed.
Returns:
EFI_SUCCESS - The keystroke information was returned.
EFI_NOT_READY - There was no keystroke data availiable.
EFI_DEVICE_ERROR - The keystroke information was not returned due to
hardware errors.
EFI_INVALID_PARAMETER - KeyData is NULL.
--*/
{
EFI_STATUS Status;
GRAPHICS_PRIVATE_DATA *Private;
Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
ZeroMem (&KeyData->Key, sizeof (KeyData->Key));
InitializeKeyState (Private, &KeyData->KeyState);
Status = GopPrivateCheckQ (&Private->QueueForRead);
if (!EFI_ERROR (Status)) {
//
// If a Key press exists try and read it.
//
Status = GopPrivateDeleteQ (Private, &Private->QueueForRead, KeyData);
if (!EFI_ERROR (Status)) {
//
// If partial keystroke is not enabled, check whether it is value key. If not return
// EFI_NOT_READY.
//
if (!Private->IsPartialKeySupport) {
if (KeyData->Key.ScanCode == SCAN_NULL && KeyData->Key.UnicodeChar == CHAR_NULL) {
Status = EFI_NOT_READY;
}
}
}
}
return Status;
}
EFI_STATUS
EFIAPI
WinNtWndKeySetState (
IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
IN EFI_KEY_TOGGLE_STATE *KeyToggleState
)
{
GRAPHICS_PRIVATE_DATA *Private;
Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
Private->KeyState.KeyToggleState = *KeyToggleState;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
WinNtWndRegisterKeyNotify (
IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack,
IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack,
IN VOID *Context
)
{
GRAPHICS_PRIVATE_DATA *Private;
Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
Private->MakeRegisterdKeyCallback = MakeCallBack;
Private->BreakRegisterdKeyCallback = BreakCallBack;
Private->RegisterdKeyCallbackContext = Context;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
WinNtWndCheckPointer (
IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo
)
{
GRAPHICS_PRIVATE_DATA *Private;
Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
return EFI_NOT_READY;
}
EFI_STATUS
EFIAPI
WinNtWndGetPointerState (
IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
IN EFI_SIMPLE_POINTER_STATE *State
)
{
GRAPHICS_PRIVATE_DATA *Private;
Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
return EFI_NOT_READY;
}