/** @file Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
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; }