| /** @file | |
| Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| 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 existence 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 available. | |
| 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->ScrollLock = FALSE; | |
| Private->NumLock = FALSE; | |
| Private->CapsLock = FALSE; | |
| Private->IsPartialKeySupport = FALSE; | |
| if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) { | |
| Private->ScrollLock = TRUE; | |
| } | |
| if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) { | |
| Private->NumLock = TRUE; | |
| } | |
| if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) { | |
| Private->CapsLock = TRUE; | |
| } | |
| if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) { | |
| Private->IsPartialKeySupport = TRUE; | |
| } | |
| 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); | |
| if (!Private->PointerStateChanged) { | |
| return EFI_NOT_READY; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| 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); | |
| if (!Private->PointerStateChanged) { | |
| return EFI_NOT_READY; | |
| } | |
| State->RelativeMovementX = Private->PointerState.RelativeMovementX; | |
| State->RelativeMovementY = Private->PointerState.RelativeMovementY; | |
| State->RelativeMovementZ = Private->PointerState.RelativeMovementZ; | |
| State->LeftButton = Private->PointerState.LeftButton; | |
| State->RightButton = Private->PointerState.RightButton; | |
| Private->PointerState.RelativeMovementX = 0; | |
| Private->PointerState.RelativeMovementY = 0; | |
| Private->PointerState.RelativeMovementZ = 0; | |
| Private->PointerStateChanged = FALSE; | |
| return EFI_SUCCESS; | |
| } |