/** @file Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent Module Name: WinNtGopInput.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 "WinNtGop.h" /** TODO: Add function description @param Private TODO: add argument description @retval EFI_SUCCESS TODO: Add description for return value **/ EFI_STATUS GopPrivateCreateQ ( IN GOP_PRIVATE_DATA *Private, IN GOP_QUEUE_FIXED *Queue ) { Private->WinNtThunk->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 GOP_PRIVATE_DATA *Private, IN GOP_QUEUE_FIXED *Queue ) { Queue->Front = 0; Queue->Rear = 0; Private->WinNtThunk->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 GOP_PRIVATE_DATA *Private, IN GOP_QUEUE_FIXED *Queue, IN EFI_KEY_DATA *KeyData ) { Private->WinNtThunk->EnterCriticalSection (&Queue->Cs); if ((Queue->Rear + 1) % MAX_Q == Queue->Front) { Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs); return EFI_NOT_READY; } CopyMem (&Queue->Q[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA)); Queue->Rear = (Queue->Rear + 1) % MAX_Q; Private->WinNtThunk->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 GOP_PRIVATE_DATA *Private, IN GOP_QUEUE_FIXED *Queue, OUT EFI_KEY_DATA *Key ) { Private->WinNtThunk->EnterCriticalSection (&Queue->Cs); if (Queue->Front == Queue->Rear) { Private->WinNtThunk->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. // Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs); ZeroMem (Key, sizeof (EFI_KEY_DATA)); return EFI_NOT_READY; } } Private->WinNtThunk->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; } 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; } 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); } } } VOID WinNtGopSimpleTextInTimerHandler ( IN EFI_EVENT Event, IN VOID *Context ) { GOP_PRIVATE_DATA *Private; EFI_KEY_DATA KeyData; Private = (GOP_PRIVATE_DATA *)Context; while (GopPrivateDeleteQ (Private, &Private->QueueForNotify, &KeyData) == EFI_SUCCESS) { GopPrivateInvokeRegisteredFunction (Private, &KeyData); } } /** Initialize the key state. @param Private The GOP_PRIVATE_DATA instance. @param KeyState A pointer to receive the key state information. **/ VOID InitializeKeyState ( IN GOP_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 GOP_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->QueueForNotify, &KeyData); GopPrivateAddQ (Private, &Private->QueueForRead, &KeyData); return EFI_SUCCESS; } 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; } 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_KEY_DATA KeyData; EFI_TPL OldTpl; // // Enter critical section // OldTpl = gBS->RaiseTPL (TPL_NOTIFY); // // A reset is draining the Queue // while (GopPrivateDeleteQ (Private, &Private->QueueForRead, &KeyData) == EFI_SUCCESS) ; while (GopPrivateDeleteQ (Private, &Private->QueueForNotify, &KeyData) == 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->IsPartialKeySupport = 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; } 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); // // Call hot key callback before telling caller there is a key available // WinNtGopSimpleTextInTimerHandler (NULL, Private); 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; } } } } // // Leave critical section and return // gBS->RestoreTPL (OldTpl); return Status; } // // Simple Text In implementation. // /** TODO: Add function description @param This TODO: add argument description @param ExtendedVerification TODO: add argument description @retval EFI_SUCCESS TODO: Add description for return value **/ EFI_STATUS EFIAPI WinNtGopSimpleTextInReset ( IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, IN BOOLEAN ExtendedVerification ) { GOP_PRIVATE_DATA *Private; Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); return GopPrivateResetWorker (Private); } /** TODO: Add function description @param This TODO: add argument description @param Key TODO: add argument description @return TODO: add return values **/ EFI_STATUS EFIAPI WinNtGopSimpleTextInReadKeyStroke ( IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, OUT EFI_INPUT_KEY *Key ) { GOP_PRIVATE_DATA *Private; EFI_STATUS Status; EFI_KEY_DATA KeyData; Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); // // Considering if the partial keystroke is enabled, there maybe a partial // keystroke in the queue, so here skip the partial keystroke and get the // next key from the queue // while (1) { Status = GopPrivateReadKeyStrokeWorker (Private, &KeyData); if (EFI_ERROR (Status)) { return Status; } if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { continue; } // // Convert Ctrl+[A-Z] to Ctrl+[1-26] // if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) { if ((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) { KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1); } else if ((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z')) { KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1); } } CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); return EFI_SUCCESS; } } /** TODO: Add function description @param Event TODO: add argument description @param Context TODO: add argument description @return TODO: add return values **/ VOID EFIAPI WinNtGopSimpleTextInWaitForKey ( IN EFI_EVENT Event, IN VOID *Context ) { GOP_PRIVATE_DATA *Private; EFI_STATUS Status; EFI_TPL OldTpl; EFI_KEY_DATA KeyData; Private = (GOP_PRIVATE_DATA *) Context; // // Enter critical section // OldTpl = gBS->RaiseTPL (TPL_NOTIFY); // // Call hot key callback before telling caller there is a key available // WinNtGopSimpleTextInTimerHandler (NULL, Private); // // WaitforKey doesn't suppor the partial key. // Considering if the partial keystroke is enabled, there maybe a partial // keystroke in the queue, so here skip the partial keystroke and get the // next key from the queue // while (1) { Status = GopPrivateCheckQ (&Private->QueueForRead); if (!EFI_ERROR (Status)) { // // If a there is a key in the queue and it is not partial keystroke, signal event. // if (Private->QueueForRead.Q[Private->QueueForRead.Front].Key.ScanCode == SCAN_NULL && Private->QueueForRead.Q[Private->QueueForRead.Front].Key.UnicodeChar == CHAR_NULL) { GopPrivateDeleteQ (Private,&Private->QueueForRead,&KeyData); continue; } gBS->SignalEvent (Event); } else { // // We need to sleep or NT will schedule this thread with such high // priority that WinProc thread will never run and we will not see // keyboard input. This Sleep makes the syste run 10x faster, so don't // remove it. // Private->WinNtThunk->Sleep (1); } break; } // // Leave critical section and return // gBS->RestoreTPL (OldTpl); } // // Simple Text Input Ex protocol functions // 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); } 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; 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; } 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 VOID **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. --*/ { 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 || KeyNotificationFunction == 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; 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 (EFI_KEY_DATA)); InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry); *NotifyHandle = NewNotify; return EFI_SUCCESS; } EFI_STATUS EFIAPI WinNtGopSimpleTextInExUnregisterKeyNotify ( IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, IN VOID *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. --*/ { GOP_PRIVATE_DATA *Private; LIST_ENTRY *Link; WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; if (NotificationHandle == NULL) { 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 == NotificationHandle) { // // Remove the notification function from NotifyList and free resources // RemoveEntryList (&CurrentNotify->NotifyEntry); gBS->FreePool (CurrentNotify); return EFI_SUCCESS; } } // // Can not find the specified Notification Handle // return EFI_INVALID_PARAMETER; } /** TODO: Add function description @param Private TODO: add argument description @return TODO: add return values **/ EFI_STATUS WinNtGopInitializeSimpleTextInForWindow ( IN GOP_PRIVATE_DATA *Private ) { EFI_STATUS Status; GopPrivateCreateQ (Private, &Private->QueueForRead); GopPrivateCreateQ (Private, &Private->QueueForNotify); // // Initialize Simple Text In protoocol // Private->SimpleTextIn.Reset = WinNtGopSimpleTextInReset; Private->SimpleTextIn.ReadKeyStroke = WinNtGopSimpleTextInReadKeyStroke; Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, WinNtGopSimpleTextInWaitForKey, Private, &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); // // Create the Timer to trigger hot key notifications // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, WinNtGopSimpleTextInTimerHandler, Private, &Private->TimerEvent ); ASSERT_EFI_ERROR (Status); Status = gBS->SetTimer ( Private->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL ); ASSERT_EFI_ERROR (Status); return Status; } /** TODO: Add function description @param Private TODO: add argument description @retval EFI_SUCCESS TODO: Add description for return value **/ EFI_STATUS WinNtGopDestroySimpleTextInForWindow ( IN GOP_PRIVATE_DATA *Private ) { gBS->CloseEvent (Private->TimerEvent); GopPrivateDestroyQ (Private, &Private->QueueForRead); GopPrivateDestroyQ (Private, &Private->QueueForNotify); return EFI_SUCCESS; }