From 66aa04e4e3a0b84369cbb483a78c4113b619663a Mon Sep 17 00:00:00 2001 From: qhuang8 Date: Fri, 19 Oct 2007 02:35:29 +0000 Subject: Update to support EFI_SIMPLE_INPUT_EX protocol git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4178 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Universal/Console/ConSplitterDxe/ConSplitter.c | 565 +++++++++++++++++++++ .../Universal/Console/ConSplitterDxe/ConSplitter.h | 185 ++++++- .../Console/ConSplitterDxe/ConSplitterDxe.inf | 2 + .../Universal/Console/TerminalDxe/Terminal.c | 88 +++- .../Universal/Console/TerminalDxe/Terminal.h | 179 ++++++- .../Universal/Console/TerminalDxe/TerminalConIn.c | 436 +++++++++++++++- .../Universal/Console/TerminalDxe/TerminalDxe.inf | 4 +- 7 files changed, 1440 insertions(+), 19 deletions(-) (limited to 'MdeModulePkg/Universal/Console') diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c index dc391e33bc..93edf82ed6 100644 --- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c @@ -43,6 +43,21 @@ STATIC TEXT_IN_SPLITTER_PRIVATE_DATA mConIn = { 0, (EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL, 0, + { + ConSplitterTextInResetEx, + ConSplitterTextInReadKeyStrokeEx, + (EFI_EVENT) NULL, + ConSplitterTextInSetState, + ConSplitterTextInRegisterKeyNotify, + ConSplitterTextInUnregisterKeyNotify + }, + 0, + (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **) NULL, + 0, + { + (struct _LIST_ENTRY *) NULL, + (struct _LIST_ENTRY *) NULL + }, { ConSplitterSimplePointerReset, @@ -367,6 +382,8 @@ Returns: &mConIn.VirtualHandle, &gEfiSimpleTextInProtocolGuid, &mConIn.TextIn, + &gEfiSimpleTextInputExProtocolGuid, + &mConIn.TextInEx, &gEfiSimplePointerProtocolGuid, &mConIn.SimplePointer, &gEfiPrimaryConsoleInDeviceGuid, @@ -514,6 +531,30 @@ Returns: ); ASSERT_EFI_ERROR (Status); + // + // Buffer for Simple Text Input Ex Protocol + // + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *), + &ConInPrivate->TextInExListCount, + (VOID **) &ConInPrivate->TextInExList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + ConSplitterTextInWaitForKey, + ConInPrivate, + &ConInPrivate->TextInEx.WaitForKeyEx + ); + ASSERT_EFI_ERROR (Status); + + InitializeListHead (&ConInPrivate->NotifyList); + + ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode; Status = ConSplitterGrowBuffer ( @@ -898,6 +939,7 @@ Returns: { EFI_STATUS Status; EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx; // // Start ConSplitter on ControllerHandle, and create the virtual @@ -915,6 +957,23 @@ Returns: return Status; } + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextInputExProtocolGuid, + (VOID **) &TextInEx, + This->DriverBindingHandle, + mConIn.VirtualHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = ConSplitterTextInExAddDevice (&mConIn, TextInEx); + if (EFI_ERROR (Status)) { + return Status; + } + return ConSplitterTextInAddDevice (&mConIn, TextIn); } @@ -1195,10 +1254,29 @@ Returns: EFI_STATUS Status; EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx; if (NumberOfChildren == 0) { return EFI_SUCCESS; } + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextInputExProtocolGuid, + (VOID **) &TextInEx, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = ConSplitterTextInExDeleteDevice (&mConIn, TextInEx); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = ConSplitterStop ( This, ControllerHandle, @@ -1512,6 +1590,66 @@ Returns: return EFI_NOT_FOUND; } +EFI_STATUS +ConSplitterTextInExAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx + ) +{ + EFI_STATUS Status; + + // + // If the TextInEx List is full, enlarge it by calling growbuffer(). + // + if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) { + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *), + &Private->TextInExListCount, + (VOID **) &Private->TextInExList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + // + // Add the new text-in device data structure into the Text In List. + // + Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx; + Private->CurrentNumberOfExConsoles++; + + // + // Extra CheckEvent added to reduce the double CheckEvent() in UI.c + // + gBS->CheckEvent (TextInEx->WaitForKeyEx); + + return EFI_SUCCESS; +} + +EFI_STATUS +ConSplitterTextInExDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx + ) +{ + UINTN Index; + // + // Remove the specified text-in device data structure from the Text In List, + // and rearrange the remaining data structures in the Text In List. + // + for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { + if (Private->TextInExList[Index] == TextInEx) { + for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) { + Private->TextInExList[Index] = Private->TextInExList[Index + 1]; + } + + Private->CurrentNumberOfExConsoles--; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + EFI_STATUS ConSplitterSimplePointerAddDevice ( IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, @@ -2760,6 +2898,433 @@ Returns: } } + +STATIC +BOOLEAN +IsKeyRegistered ( + 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; + +} + +// +// Simple Text Input Ex protocol functions +// + +EFI_STATUS +EFIAPI +ConSplitterTextInResetEx ( + 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. + EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + Private->KeyEventSignalState = FALSE; + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) { + Status = Private->TextInExList[Index]->Reset ( + Private->TextInExList[Index], + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + return ReturnStatus; + +} + +EFI_STATUS +EFIAPI +ConSplitterTextInReadKeyStrokeEx ( + 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. + +--*/ +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + EFI_STATUS Status; + UINTN Index; + EFI_KEY_DATA CurrentKeyData; + + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + if (Private->PasswordEnabled) { + // + // If StdIn Locked return not ready + // + return EFI_NOT_READY; + } + + Private->KeyEventSignalState = FALSE; + + KeyData->Key.UnicodeChar = 0; + KeyData->Key.ScanCode = SCAN_NULL; + + // + // if no physical console input device exists, return EFI_NOT_READY; + // if any physical console input device has key input, + // return the key and EFI_SUCCESS. + // + for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { + Status = Private->TextInExList[Index]->ReadKeyStrokeEx ( + Private->TextInExList[Index], + &CurrentKeyData + ); + if (!EFI_ERROR (Status)) { + CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData)); + return Status; + } + } + + return EFI_NOT_READY; +} + +EFI_STATUS +EFIAPI +ConSplitterTextInSetState ( + 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. + +--*/ +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + EFI_STATUS Status; + UINTN Index; + + if (KeyToggleState == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // if no physical console input device exists, return EFI_SUCCESS; + // otherwise return the status of setting state of physical console input device + // + for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { + Status = Private->TextInExList[Index]->SetState ( + Private->TextInExList[Index], + KeyToggleState + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +ConSplitterTextInRegisterKeyNotify ( + 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. + +--*/ +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + EFI_STATUS Status; + UINTN Index; + TEXT_IN_EX_SPLITTER_NOTIFY *NewNotify; + LIST_ENTRY *Link; + TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify; + + + if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // if no physical console input device exists, + // return EFI_SUCCESS directly. + // + if (Private->CurrentNumberOfExConsoles <= 0) { + return EFI_SUCCESS; + } + + // + // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. + // + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + TEXT_IN_EX_SPLITTER_NOTIFY, + NotifyEntry, + TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE + ); + if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { + *NotifyHandle = CurrentNotify->NotifyHandle; + return EFI_SUCCESS; + } + } + } + + // + // Allocate resource to save the notification function + // + NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY)); + if (NewNotify == NULL) { + return EFI_OUT_OF_RESOURCES; + } + NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles); + if (NewNotify->NotifyHandleList == NULL) { + gBS->FreePool (NewNotify); + return EFI_OUT_OF_RESOURCES; + } + NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE; + NewNotify->KeyNotificationFn = KeyNotificationFunction; + CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData)); + + // + // Return the wrong status of registering key notify of + // physical console input device if meet problems + // + for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { + Status = Private->TextInExList[Index]->RegisterKeyNotify ( + Private->TextInExList[Index], + KeyData, + KeyNotificationFunction, + &NewNotify->NotifyHandleList[Index] + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (NewNotify->NotifyHandleList); + gBS->FreePool (NewNotify); + return Status; + } + } + + // + // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &NewNotify->NotifyHandle, + &gSimpleTextInExNotifyGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry); + + *NotifyHandle = NewNotify->NotifyHandle; + + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +ConSplitterTextInUnregisterKeyNotify ( + 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. + +--*/ +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + EFI_STATUS Status; + UINTN Index; + TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify; + LIST_ENTRY *Link; + + 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 = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // if no physical console input device exists, + // return EFI_SUCCESS directly. + // + if (Private->CurrentNumberOfExConsoles <= 0) { + return EFI_SUCCESS; + } + + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR (Link, TEXT_IN_EX_SPLITTER_NOTIFY, NotifyEntry, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE); + if (CurrentNotify->NotifyHandle == NotificationHandle) { + for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { + Status = Private->TextInExList[Index]->UnregisterKeyNotify ( + Private->TextInExList[Index], + CurrentNotify->NotifyHandleList[Index] + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + RemoveEntryList (&CurrentNotify->NotifyEntry); + Status = gBS->UninstallMultipleProtocolInterfaces ( + CurrentNotify->NotifyHandle, + &gSimpleTextInExNotifyGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + gBS->FreePool (CurrentNotify->NotifyHandleList); + gBS->FreePool (CurrentNotify); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; + +} + + + EFI_STATUS EFIAPI ConSplitterSimplePointerReset ( diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h index 2bcf5a29e8..4a71bb6294 100644 --- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h @@ -24,6 +24,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include #include #include @@ -53,6 +54,8 @@ extern EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding; extern EFI_COMPONENT_NAME_PROTOCOL gConSplitterStdErrComponentName; extern EFI_COMPONENT_NAME2_PROTOCOL gConSplitterStdErrComponentName2; +extern EFI_GUID gSimpleTextInExNotifyGuid; + // These definitions were in the old Hii protocol, but are not in the new UEFI // version. So they are defined locally. #define UNICODE_NARROW_CHAR 0xFFF0 @@ -76,6 +79,16 @@ typedef struct { // #define TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('T', 'i', 'S', 'p') +#define TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE EFI_SIGNATURE_32 ('T', 'i', 'S', 'n') + +typedef struct _TEXT_IN_EX_SPLITTER_NOTIFY { + UINTN Signature; + EFI_HANDLE *NotifyHandleList; + EFI_HANDLE NotifyHandle; + EFI_KEY_DATA KeyData; + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; + LIST_ENTRY NotifyEntry; +} TEXT_IN_EX_SPLITTER_NOTIFY; typedef struct { UINT64 Signature; EFI_HANDLE VirtualHandle; @@ -85,6 +98,13 @@ typedef struct { EFI_SIMPLE_TEXT_INPUT_PROTOCOL **TextInList; UINTN TextInListCount; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL TextInEx; + UINTN CurrentNumberOfExConsoles; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **TextInExList; + UINTN TextInExListCount; + LIST_ENTRY NotifyList; + + EFI_SIMPLE_POINTER_PROTOCOL SimplePointer; EFI_SIMPLE_POINTER_MODE SimplePointerMode; UINTN CurrentNumberOfPointers; @@ -114,6 +134,19 @@ typedef struct { SimplePointer, \ TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \ ) +#define TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + TEXT_IN_SPLITTER_PRIVATE_DATA, \ + TextInEx, \ + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS(a) \ + CR (a, \ + TEXT_IN_SPLITTER_PRIVATE_DATA, \ + AbsolutePointer, \ + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) // // Private data for the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL splitter @@ -770,7 +803,151 @@ ConSplitterTextInReadKeyStroke ( OUT EFI_INPUT_KEY *Key ) ; +EFI_STATUS +ConSplitterTextInExAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx + ) +; + +EFI_STATUS +ConSplitterTextInExDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx + ) +; + +// +// Simple Text Input Ex protocol function prototypes +// + +EFI_STATUS +EFIAPI +ConSplitterTextInResetEx ( + 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. + EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +--*/ +; + +EFI_STATUS +EFIAPI +ConSplitterTextInReadKeyStrokeEx ( + 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. + +--*/ +; + +EFI_STATUS +EFIAPI +ConSplitterTextInSetState ( + 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 +EFIAPI +ConSplitterTextInRegisterKeyNotify ( + 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 +EFIAPI +ConSplitterTextInUnregisterKeyNotify ( + 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. + +--*/ +; VOID EFIAPI ConSplitterTextInWaitForKey ( @@ -945,10 +1122,10 @@ ConSpliterConsoleControlSetMode ( EFI_STATUS EFIAPI ConSpliterGraphicsOutputQueryMode ( - IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, - IN UINT32 ModeNumber, - OUT UINTN *SizeOfInfo, - OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info ) ; diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf index c7e4079e89..9a781a5a65 100644 --- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf @@ -67,11 +67,13 @@ gEfiPrimaryConsoleOutDeviceGuid # ALWAYS_PRODUCED gEfiPrimaryConsoleInDeviceGuid # ALWAYS_PRODUCED gEfiPrimaryStandardErrorDeviceGuid # ALWAYS_PRODUCED + gSimpleTextInExNotifyGuid # ALWAYS_PRODUCED [Protocols] gEfiConsoleControlProtocolGuid # PROTOCOL ALWAYS_PRODUCED gEfiSimplePointerProtocolGuid # PROTOCOL ALWAYS_PRODUCED gEfiSimpleTextInProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiSimpleTextInputExProtocolGuid # PROTOCOL ALWAYS_PRODUCED gEfiSimpleTextOutProtocolGuid # PROTOCOL ALWAYS_PRODUCED gEfiGraphicsOutputProtocolGuid # PROTOCOL ALWAYS_PRODUCED gEfiUgaDrawProtocolGuid # PROTOCOL ALWAYS_PRODUCED diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c index 4e2f650964..aaeca12100 100644 --- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c +++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c @@ -22,6 +22,12 @@ Revision History: #include "Terminal.h" +STATIC +EFI_STATUS +TerminalFreeNotifyList ( + IN OUT LIST_ENTRY *ListHead + ); + // // Globals // @@ -94,7 +100,19 @@ TERMINAL_DEV gTerminalDevTemplate = { NULL, INPUT_STATE_DEFAULT, RESET_STATE_DEFAULT, - FALSE + FALSE, + { // SimpleTextInputEx + TerminalConInResetEx, + TerminalConInReadKeyStrokeEx, + NULL, + TerminalConInSetState, + TerminalConInRegisterKeyNotify, + TerminalConInUnregisterKeyNotify, + }, + { + NULL, + NULL, + } }; @@ -381,6 +399,19 @@ TerminalDriverBindingStart ( TerminalDevice->TerminalType = TerminalType; TerminalDevice->SerialIo = SerialIo; + InitializeListHead (&TerminalDevice->NotifyList); + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + TerminalConInWaitForKeyEx, + &TerminalDevice->SimpleInputEx, + &TerminalDevice->SimpleInputEx.WaitForKeyEx + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, @@ -391,7 +422,6 @@ TerminalDriverBindingStart ( if (EFI_ERROR (Status)) { goto Error; } - // // initialize the FIFO buffer used for accommodating // the pre-read pending characters @@ -405,6 +435,7 @@ TerminalDriverBindingStart ( // keystroke response performance issue // Mode = TerminalDevice->SerialIo->Mode; + SerialInTimeOut = 0; if (Mode->BaudRate != 0) { SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate; @@ -578,6 +609,8 @@ TerminalDriverBindingStart ( TerminalDevice->DevicePath, &gEfiSimpleTextInProtocolGuid, &TerminalDevice->SimpleInput, + &gEfiSimpleTextInputExProtocolGuid, + &TerminalDevice->SimpleInputEx, &gEfiSimpleTextOutProtocolGuid, &TerminalDevice->SimpleTextOutput, NULL @@ -655,6 +688,12 @@ Error: gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey); } + if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) { + gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx); + } + + TerminalFreeNotifyList (&TerminalDevice->NotifyList); + if (TerminalDevice->ControllerNameTable != NULL) { FreeUnicodeStringTable (TerminalDevice->ControllerNameTable); } @@ -809,6 +848,8 @@ TerminalDriverBindingStop ( ChildHandleBuffer[Index], &gEfiSimpleTextInProtocolGuid, &TerminalDevice->SimpleInput, + &gEfiSimpleTextInputExProtocolGuid, + &TerminalDevice->SimpleInputEx, &gEfiSimpleTextOutProtocolGuid, &TerminalDevice->SimpleTextOutput, &gEfiDevicePathProtocolGuid, @@ -851,6 +892,8 @@ TerminalDriverBindingStop ( gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut); gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey); + gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx); + TerminalFreeNotifyList (&TerminalDevice->NotifyList); FreePool (TerminalDevice->DevicePath); FreePool (TerminalDevice); } @@ -868,6 +911,47 @@ TerminalDriverBindingStop ( return EFI_SUCCESS; } +STATIC +EFI_STATUS +TerminalFreeNotifyList ( + 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. + +--*/ +{ + TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode; + + if (ListHead == NULL) { + return EFI_INVALID_PARAMETER; + } + while (!IsListEmpty (ListHead)) { + NotifyNode = CR ( + ListHead->ForwardLink, + TERMINAL_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + RemoveEntryList (ListHead->ForwardLink); + gBS->FreePool (NotifyNode); + } + + return EFI_SUCCESS; +} + + + VOID TerminalUpdateConsoleDevVariable ( IN CHAR16 *VariableName, diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h index 0ae1c431f3..b352c66991 100644 --- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h +++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h @@ -30,6 +30,7 @@ Revision History #include #include #include +#include #include #include #include @@ -42,7 +43,7 @@ Revision History #include #include #include - +#include #define RAW_FIFO_MAX_NUMBER 256 @@ -68,6 +69,15 @@ typedef struct { #define TERMINAL_DEV_SIGNATURE EFI_SIGNATURE_32 ('t', 'm', 'n', 'l') +#define TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE EFI_SIGNATURE_32 ('t', 'm', 'e', 'n') + +typedef struct _TERMINAL_CONSOLE_IN_EX_NOTIFY { + UINTN Signature; + EFI_HANDLE NotifyHandle; + EFI_KEY_DATA KeyData; + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; + LIST_ENTRY NotifyEntry; +} TERMINAL_CONSOLE_IN_EX_NOTIFY; typedef struct { UINTN Signature; EFI_HANDLE Handle; @@ -94,6 +104,8 @@ typedef struct { // to indicate whether the Esc could be sent or not. // BOOLEAN OutputEscChar; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleInputEx; + LIST_ENTRY NotifyList; } TERMINAL_DEV; #define INPUT_STATE_DEFAULT 0x00 @@ -109,6 +121,7 @@ typedef struct { #define TERMINAL_CON_IN_DEV_FROM_THIS(a) CR (a, TERMINAL_DEV, SimpleInput, TERMINAL_DEV_SIGNATURE) #define TERMINAL_CON_OUT_DEV_FROM_THIS(a) CR (a, TERMINAL_DEV, SimpleTextOutput, TERMINAL_DEV_SIGNATURE) +#define TERMINAL_CON_IN_EX_DEV_FROM_THIS(a) CR (a, TERMINAL_DEV, SimpleInputEx, TERMINAL_DEV_SIGNATURE) typedef union { UINT8 Utf8_1; @@ -153,6 +166,7 @@ extern EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding; extern EFI_COMPONENT_NAME_PROTOCOL gTerminalComponentName; extern EFI_COMPONENT_NAME2_PROTOCOL gTerminalComponentName2; +extern EFI_GUID gSimpleTextInExNotifyGuid; // // Prototypes // @@ -180,6 +194,169 @@ TerminalConInReadKeyStroke ( ) ; + +BOOLEAN +IsKeyRegistered ( + 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. + +--*/ +; + +VOID +EFIAPI +TerminalConInWaitForKeyEx ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; +// +// Simple Text Input Ex protocol prototypes +// + +EFI_STATUS +EFIAPI +TerminalConInResetEx ( + 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. + EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +--*/ +; + +EFI_STATUS +EFIAPI +TerminalConInReadKeyStrokeEx ( + 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. + +--*/ +; + +EFI_STATUS +EFIAPI +TerminalConInSetState ( + 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 +EFIAPI +TerminalConInRegisterKeyNotify ( + 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 +EFIAPI +TerminalConInUnregisterKeyNotify ( + 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. + +--*/ +; + VOID EFIAPI TerminalConInWaitForKey ( diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c index 2d76e38c33..4b3eb37023 100644 --- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c +++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c @@ -1,6 +1,6 @@ /**@file - Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol. - + Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol. + Copyright (c) 2006 - 2007 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 @@ -15,6 +15,78 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "Terminal.h" +STATIC +EFI_STATUS +ReadKeyStrokeWorker ( + IN TERMINAL_DEV *TerminalDevice, + 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: + TerminalDevice - Terminal driver private structure + 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; + LIST_ENTRY *Link; + TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize *Key to nonsense value. + // + KeyData->Key.ScanCode = SCAN_NULL; + KeyData->Key.UnicodeChar = 0; + + Status = TerminalConInCheckForKey (&TerminalDevice->SimpleInput); + if (EFI_ERROR (Status)) { + return EFI_NOT_READY; + } + + if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) { + return EFI_NOT_READY; + } + + KeyData->KeyState.KeyShiftState = 0; + KeyData->KeyState.KeyToggleState = 0; + + // + // Invoke notification functions if exist + // + for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + TERMINAL_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + CurrentNotify->KeyNotificationFn (KeyData); + } + } + + return EFI_SUCCESS; + +} + + EFI_STATUS EFIAPI TerminalConInReset ( @@ -111,28 +183,358 @@ TerminalConInReadKeyStroke ( { TERMINAL_DEV *TerminalDevice; EFI_STATUS Status; + EFI_KEY_DATA KeyData; - // - // Initialize *Key to nonsense value. - // - Key->ScanCode = SCAN_NULL; - Key->UnicodeChar = 0; // // get TERMINAL_DEV from "This" parameter. // TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This); - Status = TerminalConInCheckForKey (This); + Status = ReadKeyStrokeWorker (TerminalDevice, &KeyData); if (EFI_ERROR (Status)) { - return EFI_NOT_READY; + return Status; + } + + CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); + + return EFI_SUCCESS; + +} + + +BOOLEAN +IsKeyRegistered ( + 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; + } + + return TRUE; +} + + +VOID +EFIAPI +TerminalConInWaitForKeyEx ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + Routine Description: + + Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event + Signal the event if there is key available + + Arguments: + + Event - Indicates the event that invoke this function. + + Context - Indicates the calling context. + + Returns: + + N/A + +--*/ +{ + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context); + + TerminalConInWaitForKey (Event, &TerminalDevice->SimpleInput); + +} + +// +// Simple Text Input Ex protocol functions +// + +EFI_STATUS +EFIAPI +TerminalConInResetEx ( + 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. + EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +--*/ +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This); + + Status = TerminalDevice->SimpleInput.Reset (&TerminalDevice->SimpleInput, ExtendedVerification); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; } - EfiKeyFiFoRemoveOneKey (TerminalDevice, Key); + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +TerminalConInReadKeyStrokeEx ( + 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. + +--*/ +{ + TERMINAL_DEV *TerminalDevice; + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This); + + return ReadKeyStrokeWorker (TerminalDevice, KeyData); + +} + +EFI_STATUS +EFIAPI +TerminalConInSetState ( + 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. + +--*/ +{ + if (KeyToggleState == NULL) { + return EFI_INVALID_PARAMETER; + } return EFI_SUCCESS; +} +EFI_STATUS +EFIAPI +TerminalConInRegisterKeyNotify ( + 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; + TERMINAL_DEV *TerminalDevice; + TERMINAL_CONSOLE_IN_EX_NOTIFY *NewNotify; + LIST_ENTRY *Link; + TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + + if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) { + return EFI_INVALID_PARAMETER; + } + + TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This); + + // + // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. + // + for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + TERMINAL_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE + ); + if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { + *NotifyHandle = CurrentNotify->NotifyHandle; + return EFI_SUCCESS; + } + } + } + + // + // Allocate resource to save the notification function + // + NewNotify = (TERMINAL_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY)); + if (NewNotify == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + NewNotify->Signature = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE; + NewNotify->KeyNotificationFn = KeyNotificationFunction; + CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData)); + InsertTailList (&TerminalDevice->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 +TerminalConInUnregisterKeyNotify ( + 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; + TERMINAL_DEV *TerminalDevice; + LIST_ENTRY *Link; + TERMINAL_CONSOLE_IN_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; + } + + TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This); + + for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + TERMINAL_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, + TERMINAL_CONSOLE_IN_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; + } + } + + return EFI_NOT_FOUND; +} + + VOID TranslateRawDataToEfiKey ( IN TERMINAL_DEV *TerminalDevice @@ -787,7 +1189,9 @@ Symbols used in table below | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p | | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M | | Escape | 0x17 | ESC | ESC | ESC | -+=========+======+===========+==========+=========+ +| F11 | 0x15 | | ESC ! | | +| F12 | 0x16 | | ESC @ | | ++=========+======+===========+==========+==========+ Special Mappings ================ @@ -882,6 +1286,12 @@ ESC R ESC r ESC R = Reset System case '0': Key.ScanCode = SCAN_F10; break; + case '!': + Key.ScanCode = SCAN_F11; + break; + case '@': + Key.ScanCode = SCAN_F12; + break; case 'h': Key.ScanCode = SCAN_HOME; break; @@ -1150,6 +1560,10 @@ ESC R ESC r ESC R = Reset System if (UnicodeChar == ESC) { TerminalDevice->InputState = INPUT_STATE_ESC; } + + if (UnicodeChar == CSI) { + TerminalDevice->InputState = INPUT_STATE_CSI; + } if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) { Status = gBS->SetTimer( diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf index 2e279f2a39..78446862e8 100644 --- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf @@ -58,6 +58,7 @@ UefiDriverEntryPoint DebugLib PcdLib + BaseLib [Guids] gEfiGlobalVariableGuid # SOMETIMES_CONSUMED L"ErrOutDev" @@ -65,13 +66,14 @@ gEfiVT100Guid # SOMETIMES_CONSUMED gEfiVT100PlusGuid # SOMETIMES_CONSUMED gEfiPcAnsiGuid # SOMETIMES_CONSUMED - + gSimpleTextInExNotifyGuid # SOMETIMES_CONSUMED [Protocols] gEfiHotPlugDeviceGuid # PROTOCOL SOMETIMES_CONSUMED gEfiSerialIoProtocolGuid # PROTOCOL TO_START gEfiDevicePathProtocolGuid # PROTOCOL TO_START gEfiSimpleTextInProtocolGuid # PROTOCOL BY_START + gEfiSimpleTextInputExProtocolGuid # PROTOCOL BY_START gEfiSimpleTextOutProtocolGuid # PROTOCOL BY_START [Pcd] -- cgit v1.2.3