From 62cf113f2e3741e498d22df1cf5d347fab654e57 Mon Sep 17 00:00:00 2001 From: qhuang8 Date: Fri, 19 Oct 2007 02:36:33 +0000 Subject: [PATCH] Update to support EFI_SIMPLE_INPUT_EX protocol git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4180 6f19259b-4bc3-4df7-8a09-765794883524 --- Nt32Pkg/WinNtGopDxe/WinNtGop.h | 76 ++- Nt32Pkg/WinNtGopDxe/WinNtGopDriver.c | 84 ++-- Nt32Pkg/WinNtGopDxe/WinNtGopDxe.inf | 4 +- Nt32Pkg/WinNtGopDxe/WinNtGopInput.c | 681 ++++++++++++++++++++++++--- Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c | 205 ++++++-- 5 files changed, 897 insertions(+), 153 deletions(-) diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGop.h b/Nt32Pkg/WinNtGopDxe/WinNtGop.h index 077e68105d..ac4defe11c 100644 --- a/Nt32Pkg/WinNtGopDxe/WinNtGop.h +++ b/Nt32Pkg/WinNtGopDxe/WinNtGop.h @@ -23,23 +23,40 @@ Abstract: #ifndef _WIN_NT_GOP_H_ #define _WIN_NT_GOP_H_ -//@MT:#include "EfiWinNT.h" -//@MT:#include "Tiano.h" -//@MT:#include "EfiDriverLib.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include // -// Driver Consumed Protocols -// -//@MT:#include EFI_PROTOCOL_DEFINITION (DevicePath) -//@MT:#include EFI_PROTOCOL_DEFINITION (WinNtIo) +// WM_SYSKEYDOWN/WM_SYSKEYUP Notification +// lParam +// bit 24: Specifies whether the key is an extended key, +// such as the right-hand ALT and CTRL keys that appear on +// an enhanced 101- or 102-key keyboard. +// The value is 1 if it is an extended key; otherwise, it is 0. +// bit 29:Specifies the context code. +// The value is 1 if the ALT key is down while the key is pressed/released; +// it is 0 if the WM_SYSKEYDOWN message is posted to the active window +// because no window has the keyboard focus. +#define GOP_EXTENDED_KEY (0x1 << 24) +#define GOP_ALT_KEY_PRESSED (0x1 << 29) -// -// Driver Produced Protocols -// -//@MT:#include EFI_PROTOCOL_DEFINITION (DriverBinding) -//@MT:#include EFI_PROTOCOL_DEFINITION (ComponentName) -//@MT:#include EFI_PROTOCOL_DEFINITION (GraphicsOutput) -//@MT:#include "LinkedList.h" #define MAX_Q 256 @@ -54,6 +71,16 @@ typedef struct { #define GOP_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('S', 'g', 'o', 'N') +#define WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE EFI_SIGNATURE_32 ('W', 'g', 'S', 'n') + +typedef struct _WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY { + UINTN Signature; + EFI_HANDLE NotifyHandle; + EFI_KEY_DATA KeyData; + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; + LIST_ENTRY NotifyEntry; +} WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY; + #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff typedef struct { @@ -110,6 +137,22 @@ typedef struct { CRITICAL_SECTION QCriticalSection; GOP_QUEUE_FIXED Queue; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleTextInEx; + EFI_KEY_STATE KeyState; + LIST_ENTRY NotifyList; + BOOLEAN LeftShift; + BOOLEAN RightShift; + BOOLEAN LeftAlt; + BOOLEAN RightAlt; + BOOLEAN LeftCtrl; + BOOLEAN RightCtrl; + BOOLEAN LeftLogo; + BOOLEAN RightLogo; + BOOLEAN Menu; + BOOLEAN SysReq; + BOOLEAN NumLock; + BOOLEAN ScrollLock; + BOOLEAN CapsLock; } GOP_PRIVATE_DATA; #define GOP_PRIVATE_DATA_FROM_THIS(a) \ @@ -118,6 +161,9 @@ typedef struct { #define GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS(a) \ CR(a, GOP_PRIVATE_DATA, SimpleTextIn, GOP_PRIVATE_DATA_SIGNATURE) +#define GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS(a) \ + CR(a, GOP_PRIVATE_DATA, SimpleTextInEx, GOP_PRIVATE_DATA_SIGNATURE) + // // Global Protocol Variables // @@ -125,6 +171,8 @@ extern EFI_DRIVER_BINDING_PROTOCOL gWinNtGopDriverBinding; extern EFI_COMPONENT_NAME_PROTOCOL gWinNtGopComponentName; extern EFI_COMPONENT_NAME2_PROTOCOL gWinNtGopComponentName2; +extern EFI_GUID gSimpleTextInExNotifyGuid; + // // Gop Hardware abstraction internal worker functions // diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGopDriver.c b/Nt32Pkg/WinNtGopDxe/WinNtGopDriver.c index 5f1f2c1cf0..ae29da7850 100644 --- a/Nt32Pkg/WinNtGopDxe/WinNtGopDriver.c +++ b/Nt32Pkg/WinNtGopDxe/WinNtGopDriver.c @@ -21,34 +21,47 @@ Abstract: **/ - -// -// The package level header files this module uses -// -#include -#include -// -// The protocols, PPI and GUID defintions for this module -// -#include -#include -#include -#include -#include -#include -// -// The Library classes this module consumes -// -#include -#include -#include -#include -#include -#include -#include - #include "WinNtGop.h" +STATIC +EFI_STATUS +FreeNotifyList ( + IN OUT LIST_ENTRY *ListHead + ) +/*++ + +Routine Description: + +Arguments: + + ListHead - The list head + +Returns: + + EFI_SUCCESS - Free the notify list successfully + EFI_INVALID_PARAMETER - ListHead is invalid. + +--*/ +{ + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *NotifyNode; + + if (ListHead == NULL) { + return EFI_INVALID_PARAMETER; + } + while (!IsListEmpty (ListHead)) { + NotifyNode = CR ( + ListHead->ForwardLink, + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, + NotifyEntry, + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE + ); + RemoveEntryList (ListHead->ForwardLink); + gBS->FreePool (NotifyNode); + } + + return EFI_SUCCESS; +} + EFI_DRIVER_BINDING_PROTOCOL gWinNtGopDriverBinding = { WinNtGopDriverBindingSupported, WinNtGopDriverBindingStart, @@ -188,6 +201,7 @@ WinNtGopDriverBindingStart ( Private = NULL; Private = AllocatePool (sizeof (GOP_PRIVATE_DATA)); if (Private == NULL) { + Status = EFI_OUT_OF_RESOURCES; goto Done; } // @@ -230,6 +244,8 @@ WinNtGopDriverBindingStart ( &Private->GraphicsOutput, &gEfiSimpleTextInProtocolGuid, &Private->SimpleTextIn, + &gEfiSimpleTextInputExProtocolGuid, + &Private->SimpleTextInEx, NULL ); @@ -251,6 +267,13 @@ Done: FreeUnicodeStringTable (Private->ControllerNameTable); } + if (Private->SimpleTextIn.WaitForKey != NULL) { + gBS->CloseEvent (Private->SimpleTextIn.WaitForKey); + } + if (Private->SimpleTextInEx.WaitForKeyEx != NULL) { + gBS->CloseEvent (Private->SimpleTextInEx.WaitForKeyEx); + } + FreeNotifyList (&Private->NotifyList); FreePool (Private); } } @@ -313,6 +336,8 @@ WinNtGopDriverBindingStop ( &Private->GraphicsOutput, &gEfiSimpleTextInProtocolGuid, &Private->SimpleTextIn, + &gEfiSimpleTextInputExProtocolGuid, + &Private->SimpleTextInEx, NULL ); if (!EFI_ERROR (Status)) { @@ -335,8 +360,13 @@ WinNtGopDriverBindingStop ( // Free our instance data // FreeUnicodeStringTable (Private->ControllerNameTable); + Status = gBS->CloseEvent (Private->SimpleTextIn.WaitForKey); + ASSERT_EFI_ERROR (Status); + Status = gBS->CloseEvent (Private->SimpleTextInEx.WaitForKeyEx); + ASSERT_EFI_ERROR (Status); + FreeNotifyList (&Private->NotifyList); - FreePool (Private); + gBS->FreePool (Private); } diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGopDxe.inf b/Nt32Pkg/WinNtGopDxe/WinNtGopDxe.inf index 0397e323fd..2b8e4689da 100644 --- a/Nt32Pkg/WinNtGopDxe/WinNtGopDxe.inf +++ b/Nt32Pkg/WinNtGopDxe/WinNtGopDxe.inf @@ -46,6 +46,7 @@ [Packages] MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec Nt32Pkg/Nt32Pkg.dec @@ -62,10 +63,11 @@ [Guids] gEfiEventExitBootServicesGuid # SOMETIMES_CONSUMED Create Event: EVENT_GROUP_GUID gEfiWinNtGopGuid # ALWAYS_CONSUMED - + gSimpleTextInExNotifyGuid # ALWAYS_CONSUMED [Protocols] gEfiGraphicsOutputProtocolGuid # PROTOCOL BY_START gEfiSimpleTextInProtocolGuid # PROTOCOL BY_START + gEfiSimpleTextInputExProtocolGuid # PROTOCOL BY_START gEfiWinNtIoProtocolGuid # PROTOCOL TO_START diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGopInput.c b/Nt32Pkg/WinNtGopDxe/WinNtGopInput.c index a604dad4e5..0ea802355d 100644 --- a/Nt32Pkg/WinNtGopDxe/WinNtGopInput.c +++ b/Nt32Pkg/WinNtGopDxe/WinNtGopInput.c @@ -28,30 +28,6 @@ Abstract: **/ -// -// The package level header files this module uses -// -#include -#include -// -// The protocols, PPI and GUID defintions for this module -// -#include -#include -#include -#include -#include -#include -// -// The Library classes this module consumes -// -#include -#include -#include -#include -#include -#include -#include #include "WinNtGop.h" @@ -182,6 +158,301 @@ GopPrivateCheckQ ( return EFI_SUCCESS; } +STATIC +BOOLEAN +GopPrivateIsKeyRegistered ( + IN EFI_KEY_DATA *RegsiteredData, + IN EFI_KEY_DATA *InputData + ) +/*++ + +Routine Description: + +Arguments: + + RegsiteredData - A pointer to a buffer that is filled in with the keystroke + state data for the key that was registered. + InputData - A pointer to a buffer that is filled in with the keystroke + state data for the key that was pressed. + +Returns: + TRUE - Key be pressed matches a registered key. + FLASE - Match failed. + +--*/ +{ + ASSERT (RegsiteredData != NULL && InputData != NULL); + + if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) || + (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) { + return FALSE; + } + + // + // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored. + // + if (RegsiteredData->KeyState.KeyShiftState != 0 && + RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) { + return FALSE; + } + if (RegsiteredData->KeyState.KeyToggleState != 0 && + RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) { + return FALSE; + } + + return TRUE; + +} + + +STATIC +VOID +GopPrivateInvokeRegisteredFunction ( + IN GOP_PRIVATE_DATA *Private, + IN EFI_KEY_DATA *KeyData + ) +/*++ + +Routine Description: + + This function updates the status light of NumLock, ScrollLock and CapsLock. + +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 status light is updated successfully. + +--*/ +{ + LIST_ENTRY *Link; + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; + + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, + NotifyEntry, + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE + ); + if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + CurrentNotify->KeyNotificationFn (KeyData); + } + } +} + +STATIC +EFI_STATUS +GopPrivateUpdateStatusLight ( + IN GOP_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + This function updates the status light of NumLock, ScrollLock and CapsLock. + +Arguments: + + Private - The private structure of WinNt console In/Out. + +Returns: + + EFI_SUCCESS - The status light is updated successfully. + +--*/ +{ + // + // BUGBUG:Only SendInput/keybd_event function can toggle + // NumLock, CapsLock and ScrollLock keys. + // Neither of these functions is included in EFI_WIN_NT_THUNK_PROTOCOL. + // Thus, return immediately without operation. + // + return EFI_SUCCESS; + +} + + +STATIC +EFI_STATUS +GopPrivateResetWorker ( + IN GOP_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + This function is a worker function for SimpleTextIn/SimpleTextInEx.Reset(). + +Arguments: + + Private - WinNT GOP private structure + +Returns: + + EFI_SUCCESS - Reset successfully + +--*/ +{ + EFI_INPUT_KEY Key; + EFI_TPL OldTpl; + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // A reset is draining the Queue + // + while (GopPrivateDeleteQ (Private, &Key) == EFI_SUCCESS) + ; + + Private->LeftShift = FALSE; + Private->RightShift = FALSE; + Private->LeftAlt = FALSE; + Private->RightAlt = FALSE; + Private->LeftCtrl = FALSE; + Private->RightCtrl = FALSE; + Private->LeftLogo = FALSE; + Private->RightLogo = FALSE; + Private->Menu = FALSE; + Private->SysReq = FALSE; + + Private->CapsLock = FALSE; + Private->NumLock = FALSE; + Private->ScrollLock = FALSE; + + Private->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID; + Private->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID; + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GopPrivateReadKeyStrokeWorker ( + IN GOP_PRIVATE_DATA *Private, + OUT 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; + EFI_TPL OldTpl; + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Status = GopPrivateCheckQ (Private); + if (!EFI_ERROR (Status)) { + // + // If a Key press exists try and read it. + // + Status = GopPrivateDeleteQ (Private, &KeyData->Key); + if (!EFI_ERROR (Status)) { + // + // Record Key shift state and toggle state + // + if (Private->LeftCtrl) { + Private->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED; + } + if (Private->RightCtrl) { + Private->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED; + } + if (Private->LeftAlt) { + Private->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED; + } + if (Private->RightAlt) { + Private->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED; + } + if (Private->LeftShift) { + Private->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED; + } + if (Private->RightShift) { + Private->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED; + } + if (Private->LeftLogo) { + Private->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED; + } + if (Private->RightLogo) { + Private->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED; + } + if (Private->Menu) { + Private->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED; + } + if (Private->SysReq) { + Private->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED; + } + if (Private->CapsLock) { + Private->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE; + } + if (Private->NumLock) { + Private->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE; + } + if (Private->ScrollLock) { + Private->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE; + } + + KeyData->KeyState.KeyShiftState = Private->KeyState.KeyShiftState; + KeyData->KeyState.KeyToggleState = Private->KeyState.KeyToggleState; + + Private->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID; + Private->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID; + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + GopPrivateInvokeRegisteredFunction (Private, KeyData); + + return EFI_SUCCESS; + } + } + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return Status; + +} + + // // Simple Text In implementation. // @@ -204,27 +475,10 @@ WinNtGopSimpleTextInReset ( ) { GOP_PRIVATE_DATA *Private; - EFI_INPUT_KEY Key; - EFI_TPL OldTpl; Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // A reset is draining the Queue - // - while (GopPrivateDeleteQ (Private, &Key) == EFI_SUCCESS) - ; - - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - return EFI_SUCCESS; + return GopPrivateResetWorker (Private); } @@ -247,29 +501,18 @@ WinNtGopSimpleTextInReadKeyStroke ( { GOP_PRIVATE_DATA *Private; EFI_STATUS Status; - EFI_TPL OldTpl; + EFI_KEY_DATA KeyData; Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); - // - // Enter critical section - // - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - Status = GopPrivateCheckQ (Private); - if (!EFI_ERROR (Status)) { - // - // If a Key press exists try and read it. - // - Status = GopPrivateDeleteQ (Private, Key); + Status = GopPrivateReadKeyStrokeWorker (Private, &KeyData); + if (EFI_ERROR (Status)) { + return Status; } - // - // Leave critical section and return - // - gBS->RestoreTPL (OldTpl); - - return Status; + CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); + + return EFI_SUCCESS; } @@ -323,6 +566,302 @@ WinNtGopSimpleTextInWaitForKey ( gBS->RestoreTPL (OldTpl); } +// +// Simple Text Input Ex protocol functions +// + +STATIC +EFI_STATUS +EFIAPI +WinNtGopSimpleTextInExResetEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the input device and optionaly run diagnostics + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The device was reset. + +--*/ +{ + GOP_PRIVATE_DATA *Private; + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); + + return GopPrivateResetWorker (Private); +} + +STATIC +EFI_STATUS +EFIAPI +WinNtGopSimpleTextInExReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT 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: + This - Protocol instance pointer. + 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. + +--*/ +{ + GOP_PRIVATE_DATA *Private; + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); + + return GopPrivateReadKeyStrokeWorker (Private, KeyData); + +} + +EFI_STATUS +EFIAPI +WinNtGopSimpleTextInExSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState + ) +/*++ + + Routine Description: + Set certain state for the input device. + + Arguments: + This - Protocol instance pointer. + KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the + state for the input device. + + Returns: + EFI_SUCCESS - The device state was set successfully. + EFI_DEVICE_ERROR - The device is not functioning correctly and could + not have the setting adjusted. + EFI_UNSUPPORTED - The device does not have the ability to set its state. + EFI_INVALID_PARAMETER - KeyToggleState is NULL. + +--*/ +{ + EFI_STATUS Status; + GOP_PRIVATE_DATA *Private; + + if (KeyToggleState == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); + + if (((Private->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) || + ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) { + return EFI_UNSUPPORTED; + } + + Private->ScrollLock = FALSE; + Private->NumLock = FALSE; + Private->CapsLock = 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; + } + + Status = GopPrivateUpdateStatusLight (Private); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Private->KeyState.KeyToggleState = *KeyToggleState; + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +WinNtGopSimpleTextInExRegisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT EFI_HANDLE *NotifyHandle + ) +/*++ + + Routine Description: + Register a notification function for a particular keystroke for the input device. + + Arguments: + This - Protocol instance pointer. + KeyData - A pointer to a buffer that is filled in with the keystroke + information data for the key that was pressed. + KeyNotificationFunction - Points to the function to be called when the key + sequence is typed specified by KeyData. + NotifyHandle - Points to the unique handle assigned to the registered notification. + + Returns: + EFI_SUCCESS - The notification function was registered successfully. + EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures. + EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. + +--*/ +{ + EFI_STATUS Status; + GOP_PRIVATE_DATA *Private; + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; + LIST_ENTRY *Link; + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *NewNotify; + + if (KeyData == NULL || NotifyHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); + + // + // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. + // + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, + NotifyEntry, + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE + ); + if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { + *NotifyHandle = CurrentNotify->NotifyHandle; + return EFI_SUCCESS; + } + } + } + + // + // Allocate resource to save the notification function + // + NewNotify = (WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *) AllocateZeroPool (sizeof (WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY)); + if (NewNotify == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + NewNotify->Signature = WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE; + NewNotify->KeyNotificationFn = KeyNotificationFunction; + CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData)); + InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry); + + // + // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &NewNotify->NotifyHandle, + &gSimpleTextInExNotifyGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + *NotifyHandle = NewNotify->NotifyHandle; + + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +WinNtGopSimpleTextInExUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle + ) +/*++ + + Routine Description: + Remove a registered notification function from a particular keystroke. + + Arguments: + This - Protocol instance pointer. + NotificationHandle - The handle of the notification function being unregistered. + + Returns: + EFI_SUCCESS - The notification function was unregistered successfully. + EFI_INVALID_PARAMETER - The NotificationHandle is invalid. + EFI_NOT_FOUND - Can not find the matching entry in database. + +--*/ +{ + EFI_STATUS Status; + GOP_PRIVATE_DATA *Private; + LIST_ENTRY *Link; + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; + + if (NotificationHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->OpenProtocol ( + NotificationHandle, + &gSimpleTextInExNotifyGuid, + NULL, + NULL, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); + + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, + NotifyEntry, + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE + ); + if (CurrentNotify->NotifyHandle == NotificationHandle) { + // + // Remove the notification function from NotifyList and free resources + // + RemoveEntryList (&CurrentNotify->NotifyEntry); + Status = gBS->UninstallMultipleProtocolInterfaces ( + CurrentNotify->NotifyHandle, + &gSimpleTextInExNotifyGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + gBS->FreePool (CurrentNotify); + return EFI_SUCCESS; + } + } + + // + // Can not find the specified Notification Handle + // + return EFI_NOT_FOUND; +} /** TODO: Add function description @@ -355,10 +894,32 @@ WinNtGopInitializeSimpleTextInForWindow ( &Private->SimpleTextIn.WaitForKey ); + + Private->SimpleTextInEx.Reset = WinNtGopSimpleTextInExResetEx; + Private->SimpleTextInEx.ReadKeyStrokeEx = WinNtGopSimpleTextInExReadKeyStrokeEx; + Private->SimpleTextInEx.SetState = WinNtGopSimpleTextInExSetState; + Private->SimpleTextInEx.RegisterKeyNotify = WinNtGopSimpleTextInExRegisterKeyNotify; + Private->SimpleTextInEx.UnregisterKeyNotify = WinNtGopSimpleTextInExUnregisterKeyNotify; + + Private->SimpleTextInEx.Reset (&Private->SimpleTextInEx, FALSE); + + InitializeListHead (&Private->NotifyList); + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + WinNtGopSimpleTextInWaitForKey, + Private, + &Private->SimpleTextInEx.WaitForKeyEx + ); + ASSERT_EFI_ERROR (Status); + + return Status; } + /** TODO: Add function description diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c b/Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c index e027071228..58ddb1c656 100644 --- a/Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c +++ b/Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c @@ -21,30 +21,6 @@ Abstract: **/ -// -// The package level header files this module uses -// -#include -#include -// -// The protocols, PPI and GUID defintions for this module -// -#include -#include -#include -#include -#include -#include -// -// The Library classes this module consumes -// -#include -#include -#include -#include -#include -#include -#include #include "WinNtGop.h" @@ -77,6 +53,110 @@ KillNtGopThread ( IN VOID *Context ); +STATIC +VOID +WinNtGopConvertParamToEfiKeyShiftState ( + IN GOP_PRIVATE_DATA *Private, + IN WPARAM *wParam, + IN BOOLEAN Flag + ) +{ + switch (*wParam) { + // + // BUGBUG: Only GetAsyncKeyState() and GetKeyState() can distinguish + // left and right Ctrl, and Shift key. + // Neither of the two is defined in EFI_WIN_NT_THUNK_PROTOCOL. + // Therefor, we can not set the correct Shift state here. + // + case VK_SHIFT: + Private->LeftShift = Flag; + break; + case VK_CONTROL: + Private->LeftCtrl = Flag; + break; + case VK_LWIN: + Private->LeftLogo = Flag; + break; + case VK_RWIN: + Private->RightLogo = Flag; + break; + case VK_APPS: + Private->Menu = Flag; + break; + // + // BUGBUG: PrintScreen/SysRq can not trigger WM_KEYDOWN message, + // so SySReq shift state is not supported here. + // + case VK_PRINT: + Private->SysReq = Flag; + break; + } +} + +STATIC +VOID +WinNtGopConvertParamToEfiKey ( + IN GOP_PRIVATE_DATA *Private, + IN WPARAM *wParam, + IN EFI_INPUT_KEY *Key + ) +{ + switch (*wParam) { + case VK_HOME: Key->ScanCode = SCAN_HOME; break; + case VK_END: Key->ScanCode = SCAN_END; break; + case VK_LEFT: Key->ScanCode = SCAN_LEFT; break; + case VK_RIGHT: Key->ScanCode = SCAN_RIGHT; break; + case VK_UP: Key->ScanCode = SCAN_UP; break; + case VK_DOWN: Key->ScanCode = SCAN_DOWN; break; + case VK_DELETE: Key->ScanCode = SCAN_DELETE; break; + case VK_INSERT: Key->ScanCode = SCAN_INSERT; break; + case VK_PRIOR: Key->ScanCode = SCAN_PAGE_UP; break; + case VK_NEXT: Key->ScanCode = SCAN_PAGE_DOWN; break; + case VK_ESCAPE: Key->ScanCode = SCAN_ESC; break; + + case VK_F1: Key->ScanCode = SCAN_F1; break; + case VK_F2: Key->ScanCode = SCAN_F2; break; + case VK_F3: Key->ScanCode = SCAN_F3; break; + case VK_F4: Key->ScanCode = SCAN_F4; break; + case VK_F5: Key->ScanCode = SCAN_F5; break; + case VK_F6: Key->ScanCode = SCAN_F6; break; + case VK_F7: Key->ScanCode = SCAN_F7; break; + case VK_F8: Key->ScanCode = SCAN_F8; break; + case VK_F9: Key->ScanCode = SCAN_F9; break; + case VK_F11: Key->ScanCode = SCAN_F11; break; + case VK_F12: Key->ScanCode = SCAN_F12; break; + + case VK_F13: Key->ScanCode = SCAN_F13; break; + case VK_F14: Key->ScanCode = SCAN_F14; break; + case VK_F15: Key->ScanCode = SCAN_F15; break; + case VK_F16: Key->ScanCode = SCAN_F16; break; + case VK_F17: Key->ScanCode = SCAN_F17; break; + case VK_F18: Key->ScanCode = SCAN_F18; break; + case VK_F19: Key->ScanCode = SCAN_F19; break; + case VK_F20: Key->ScanCode = SCAN_F20; break; + case VK_F21: Key->ScanCode = SCAN_F21; break; + case VK_F22: Key->ScanCode = SCAN_F22; break; + case VK_F23: Key->ScanCode = SCAN_F23; break; + case VK_F24: Key->ScanCode = SCAN_F24; break; + + // + // Set toggle state + // + case VK_NUMLOCK: + Private->NumLock = !Private->NumLock; + break; + case VK_SCROLL: + Private->ScrollLock = !Private->ScrollLock; + break; + case VK_CAPITAL: + Private->CapsLock = !Private->CapsLock; + break; + } + + WinNtGopConvertParamToEfiKeyShiftState (Private, wParam, TRUE); +} + + // // GOP Protocol Member Functions // @@ -127,7 +207,7 @@ WinNtGopQuerytMode ( (*Info)->Version = 0; (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution; (*Info)->VerticalResolution = Private->ModeData[ModeNumber].VerticalResolution; - (*Info)->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; + (*Info)->PixelFormat = PixelBltOnly; (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution; return EFI_SUCCESS; @@ -615,6 +695,8 @@ WinNtGopThreadWindowProc ( // // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case + // WM_SYSKEYDOWN is posted when F10 is pressed or + // holds down ALT key and then presses another key. // case WM_SYSKEYDOWN: Key.ScanCode = 0; @@ -625,34 +707,22 @@ WinNtGopThreadWindowProc ( GopPrivateAddQ (Private, Key); return 0; } - break; - case WM_KEYDOWN: - Key.ScanCode = 0; - switch (wParam) { - case VK_HOME: Key.ScanCode = SCAN_HOME; break; - case VK_END: Key.ScanCode = SCAN_END; break; - case VK_LEFT: Key.ScanCode = SCAN_LEFT; break; - case VK_RIGHT: Key.ScanCode = SCAN_RIGHT; break; - case VK_UP: Key.ScanCode = SCAN_UP; break; - case VK_DOWN: Key.ScanCode = SCAN_DOWN; break; - case VK_DELETE: Key.ScanCode = SCAN_DELETE; break; - case VK_INSERT: Key.ScanCode = SCAN_INSERT; break; - case VK_PRIOR: Key.ScanCode = SCAN_PAGE_UP; break; - case VK_NEXT: Key.ScanCode = SCAN_PAGE_DOWN; break; - case VK_ESCAPE: Key.ScanCode = SCAN_ESC; break; + if ((lParam & GOP_ALT_KEY_PRESSED) == GOP_ALT_KEY_PRESSED) { + // + // ALT is pressed with another key pressed + // + WinNtGopConvertParamToEfiKey (Private, &wParam, &Key); - case VK_F1: Key.ScanCode = SCAN_F1; break; - case VK_F2: Key.ScanCode = SCAN_F2; break; - case VK_F3: Key.ScanCode = SCAN_F3; break; - case VK_F4: Key.ScanCode = SCAN_F4; break; - case VK_F5: Key.ScanCode = SCAN_F5; break; - case VK_F6: Key.ScanCode = SCAN_F6; break; - case VK_F7: Key.ScanCode = SCAN_F7; break; - case VK_F8: Key.ScanCode = SCAN_F8; break; - case VK_F9: Key.ScanCode = SCAN_F9; break; - case VK_F11: Key.ScanCode = SCAN_F11; break; - case VK_F12: Key.ScanCode = SCAN_F12; break; + if ((lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) { + Private->RightAlt = TRUE; + } else { + Private->LeftAlt = TRUE; + } + + if (Private->RightAlt && Private->LeftAlt) { + Private->LeftAlt = FALSE; + } } if (Key.ScanCode != 0) { @@ -662,6 +732,39 @@ WinNtGopThreadWindowProc ( return 0; + case WM_SYSKEYUP: + if ((lParam & GOP_ALT_KEY_PRESSED) == GOP_ALT_KEY_PRESSED) { + // + // ALT is pressed with another key released + // + WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, FALSE); + // + // Actually ALT key is still held down here. + // Change the ALT key state when another key is released + // by user because we did not find a better solution to + // get a released ALT key. + // + Private->RightAlt = FALSE; + Private->LeftAlt = FALSE; + } + + return 0; + + + case WM_KEYDOWN: + Key.ScanCode = 0; + WinNtGopConvertParamToEfiKey (Private, &wParam, &Key); + if (Key.ScanCode != 0) { + Key.UnicodeChar = 0; + GopPrivateAddQ (Private, Key); + } + + return 0; + + case WM_KEYUP: + WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, FALSE); + return 0; + case WM_CHAR: // // The ESC key also generate WM_CHAR.