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