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