summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf5
-rw-r--r--MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c634
-rw-r--r--MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.h172
-rw-r--r--MdeModulePkg/Bus/Usb/UsbKbDxe/keyboard.c210
-rw-r--r--MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c565
-rw-r--r--MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h185
-rw-r--r--MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf2
-rw-r--r--MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c88
-rw-r--r--MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h179
-rw-r--r--MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c436
-rw-r--r--MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf4
11 files changed, 2387 insertions, 93 deletions
diff --git a/MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf b/MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
index 34017086a4..a075c0e1ab 100644
--- a/MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+++ b/MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
@@ -55,16 +55,17 @@
DebugLib
PcdLib
UsbLib
-
+ BaseLib
[Guids]
gEfiHotPlugDeviceGuid # ALWAYS_CONSUMED
-
+ gSimpleTextInExNotifyGuid # ALWAYS_CONSUMED
[Protocols]
gEfiUsbIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSimpleTextInProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSimpleTextInputExProtocolGuid # PROTOCOL ALWAYS_CONSUMED
[FixedPcd]
gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueKeyboardEnable
diff --git a/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c b/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c
index 62fec041c3..eee3827c23 100644
--- a/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c
+++ b/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.c
@@ -100,6 +100,18 @@ USBKeyboardCheckForKey (
EFI_GUID gEfiUsbKeyboardDriverGuid = {
0xa05f5f78, 0xfb3, 0x4d10, {0x90, 0x90, 0xac, 0x4, 0x6e, 0xeb, 0x7c, 0x3c}
};
+STATIC
+EFI_STATUS
+KbdFreeNotifyList (
+ IN OUT LIST_ENTRY *ListHead
+ );
+STATIC
+BOOLEAN
+IsKeyRegistered (
+ IN EFI_KEY_DATA *RegsiteredData,
+ IN EFI_KEY_DATA *InputData
+ );
+
//
// USB Keyboard Driver Global Variables
@@ -349,6 +361,27 @@ USBKeyboardDriverBindingStart (
UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;
UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;
UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;
+
+ UsbKeyboardDevice->SimpleInputEx.Reset = USBKeyboardResetEx;
+ UsbKeyboardDevice->SimpleInputEx.ReadKeyStrokeEx = USBKeyboardReadKeyStrokeEx;
+ UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState;
+ UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify;
+ UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify;
+
+ InitializeListHead (&UsbKeyboardDevice->NotifyList);
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_NOTIFY,
+ USBKeyboardWaitForKey,
+ UsbKeyboardDevice,
+ &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx)
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
Status = gBS->CreateEvent (
EVT_NOTIFY_WAIT,
TPL_NOTIFY,
@@ -380,6 +413,8 @@ USBKeyboardDriverBindingStart (
&Controller,
&gEfiSimpleTextInProtocolGuid,
&UsbKeyboardDevice->SimpleInput,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &UsbKeyboardDevice->SimpleInputEx,
&gEfiHotPlugDeviceGuid,
NULL,
NULL
@@ -405,13 +440,15 @@ USBKeyboardDriverBindingStart (
);
if (EFI_ERROR (Status)) {
gBS->UninstallMultipleProtocolInterfaces (
- Controller,
- &gEfiSimpleTextInProtocolGuid,
- &UsbKeyboardDevice->SimpleInput,
- &gEfiHotPlugDeviceGuid,
- NULL,
- NULL
- );
+ Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ &UsbKeyboardDevice->SimpleInput,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &UsbKeyboardDevice->SimpleInputEx,
+ &gEfiHotPlugDeviceGuid,
+ NULL,
+ NULL
+ );
gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
gBS->FreePool (UsbKeyboardDevice);
gBS->CloseProtocol (
@@ -442,13 +479,15 @@ USBKeyboardDriverBindingStart (
if (EFI_ERROR (Status)) {
gBS->UninstallMultipleProtocolInterfaces (
- Controller,
- &gEfiSimpleTextInProtocolGuid,
- &UsbKeyboardDevice->SimpleInput,
- &gEfiHotPlugDeviceGuid,
- NULL,
- NULL
- );
+ Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ &UsbKeyboardDevice->SimpleInput,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &UsbKeyboardDevice->SimpleInputEx,
+ &gEfiHotPlugDeviceGuid,
+ NULL,
+ NULL
+ );
gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
gBS->FreePool (UsbKeyboardDevice);
gBS->CloseProtocol (
@@ -478,6 +517,27 @@ USBKeyboardDriverBindingStart (
return EFI_SUCCESS;
+
+ErrorExit:
+ if (UsbKeyboardDevice != NULL) {
+ if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
+ }
+ if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);
+ }
+ KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);
+ gBS->FreePool (UsbKeyboardDevice);
+ UsbKeyboardDevice = NULL;
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+
}
@@ -518,7 +578,17 @@ USBKeyboardDriverBindingStop (
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
-
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSimpleTextInputExProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
//
// Get USB_KB_DEV instance.
//
@@ -565,6 +635,8 @@ USBKeyboardDriverBindingStop (
Controller,
&gEfiSimpleTextInProtocolGuid,
&UsbKeyboardDevice->SimpleInput,
+ &gEfiSimpleTextInputExProtocolGuid,
+ &UsbKeyboardDevice->SimpleInputEx,
&gEfiHotPlugDeviceGuid,
NULL,
NULL
@@ -575,6 +647,8 @@ USBKeyboardDriverBindingStop (
gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey);
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);
+ KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);
if (UsbKeyboardDevice->ControllerNameTable != NULL) {
FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);
@@ -586,20 +660,107 @@ USBKeyboardDriverBindingStop (
}
+STATIC
+EFI_STATUS
+USBKeyboardReadKeyStrokeWorker (
+ IN USB_KB_DEV *UsbKeyboardDevice,
+ 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:
+ UsbKeyboardDevice - Usb keyboard private structure.
+ KeyData - A pointer to a buffer that is filled in with the keystroke
+ state data for the key that was pressed.
-/**
- Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset() function.
+ 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.
- This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
- ExtendedVerification
- Indicates that the driver may perform a more exhaustive
- verification operation of the device during reset.
+--*/
+{
- @retval EFI_SUCCESS Success
- @retval EFI_DEVICE_ERROR Hardware Error
+ EFI_STATUS Status;
+ UINT8 KeyChar;
+ LIST_ENTRY *Link;
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
+ EFI_KEY_DATA OriginalKeyData;
-**/
+ if (KeyData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // if there is no saved ASCII byte, fetch it
+ // by calling USBKeyboardCheckForKey().
+ //
+ if (UsbKeyboardDevice->CurKeyChar == 0) {
+ Status = USBKeyboardCheckForKey (UsbKeyboardDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ KeyData->Key.UnicodeChar = 0;
+ KeyData->Key.ScanCode = SCAN_NULL;
+
+ KeyChar = UsbKeyboardDevice->CurKeyChar;
+
+ UsbKeyboardDevice->CurKeyChar = 0;
+
+ //
+ // Translate saved ASCII byte into EFI_INPUT_KEY
+ //
+ Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, &KeyData->Key);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (&KeyData->KeyState, &UsbKeyboardDevice->KeyState, sizeof (KeyData->KeyState));
+
+ UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+ UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
+
+ //
+ //Switch the control value to their original characters. In USBKeyCodeToEFIScanCode() the CTRL-Alpha characters have been switched to
+ // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A), here switch them back for notification function.
+ //
+ CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));
+ if (UsbKeyboardDevice->CtrlOn) {
+ if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {
+ if (UsbKeyboardDevice->CapsOn) {
+ OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'A' - 1);
+ } else {
+ OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'a' - 1);
+ }
+ }
+ }
+
+ //
+ // Invoke notification functions if exist
+ //
+ for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = CR (
+ Link,
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+ );
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) {
+ CurrentNotify->KeyNotificationFn (&OriginalKeyData);
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
EFI_STATUS
EFIAPI
USBKeyboardReset (
@@ -668,36 +829,20 @@ USBKeyboardReadKeyStroke (
OUT EFI_INPUT_KEY *Key
)
{
- USB_KB_DEV *UsbKeyboardDevice;
- EFI_STATUS Status;
- UINT8 KeyChar;
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_STATUS Status;
+ EFI_KEY_DATA KeyData;
UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
- //
- // if there is no saved ASCII byte, fetch it
- // by calling USBKeyboardCheckForKey().
- //
- if (UsbKeyboardDevice->CurKeyChar == 0) {
- Status = USBKeyboardCheckForKey (UsbKeyboardDevice);
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);
+ if (EFI_ERROR (Status)) {
+ return Status;
}
- Key->UnicodeChar = 0;
- Key->ScanCode = SCAN_NULL;
-
- KeyChar = UsbKeyboardDevice->CurKeyChar;
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
- UsbKeyboardDevice->CurKeyChar = 0;
-
- //
- // Translate saved ASCII byte into EFI_INPUT_KEY
- //
- Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, Key);
-
- return Status;
+ return EFI_SUCCESS;
}
@@ -792,3 +937,396 @@ KbdReportStatusCode (
DevicePath
);
}
+STATIC
+EFI_STATUS
+KbdFreeNotifyList (
+ 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.
+
+--*/
+{
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
+
+ if (ListHead == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ while (!IsListEmpty (ListHead)) {
+ NotifyNode = CR (
+ ListHead->ForwardLink,
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+ );
+ RemoveEntryList (ListHead->ForwardLink);
+ gBS->FreePool (NotifyNode);
+ }
+
+ return EFI_SUCCESS;
+}
+
+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
+USBKeyboardResetEx (
+ 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;
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_TPL OldTpl;
+
+
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
+
+ Status = UsbKeyboardDevice->SimpleInput.Reset (&UsbKeyboardDevice->SimpleInput, ExtendedVerification);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
+ UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+EFIAPI
+USBKeyboardReadKeyStrokeEx (
+ 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.
+
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+
+ if (KeyData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
+
+ return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);
+
+}
+
+EFI_STATUS
+EFIAPI
+USBKeyboardSetState (
+ 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.
+
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+
+ if (KeyToggleState == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
+
+ if (((UsbKeyboardDevice->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||
+ ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Update the status light
+ //
+
+ UsbKeyboardDevice->ScrollOn = 0;
+ UsbKeyboardDevice->NumLockOn = 0;
+ UsbKeyboardDevice->CapsOn = 0;
+
+ if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
+ UsbKeyboardDevice->ScrollOn = 1;
+ }
+ if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
+ UsbKeyboardDevice->NumLockOn = 1;
+ }
+ if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
+ UsbKeyboardDevice->CapsOn = 1;
+ }
+
+ SetKeyLED (UsbKeyboardDevice);
+
+ UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+EFIAPI
+USBKeyboardRegisterKeyNotify (
+ 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.
+
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_STATUS Status;
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;
+ LIST_ENTRY *Link;
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
+
+ if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
+
+ //
+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
+ //
+ for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = CR (
+ Link,
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ USB_KB_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 = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));
+ if (NewNotify == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
+ NewNotify->KeyNotificationFn = KeyNotificationFunction;
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
+ InsertTailList (&UsbKeyboardDevice->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
+USBKeyboardUnregisterKeyNotify (
+ 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.
+
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_STATUS Status;
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
+ LIST_ENTRY *Link;
+
+ if (NotificationHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
+
+ Status = gBS->OpenProtocol (
+ NotificationHandle,
+ &gSimpleTextInExNotifyGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {
+ CurrentNotify = CR (
+ Link,
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+ NotifyEntry,
+ USB_KB_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;
+}
+
diff --git a/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.h b/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.h
index 710ec7c19e..bab22a3b88 100644
--- a/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.h
+++ b/MdeModulePkg/Bus/Usb/UsbKbDxe/efikey.h
@@ -26,6 +26,7 @@ Revision History
#include <PiDxe.h>
#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextInEx.h>
#include <Guid/HotPlugDevice.h>
#include <Protocol/UsbIo.h>
#include <Protocol/DevicePath.h>
@@ -40,7 +41,7 @@ Revision History
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/UsbLib.h>
-
+#include <Library/BaseLib.h>
#include <IndustryStandard/Usb.h>
@@ -69,12 +70,22 @@ typedef struct {
} USB_KB_BUFFER;
#define USB_KB_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'k', 'b', 'd')
+#define USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE EFI_SIGNATURE_32 ('u', 'k', 'b', 'x')
+
+typedef struct _KEYBOARD_CONSOLE_IN_EX_NOTIFY {
+ UINTN Signature;
+ EFI_HANDLE NotifyHandle;
+ EFI_KEY_DATA KeyData;
+ EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn;
+ LIST_ENTRY NotifyEntry;
+} KEYBOARD_CONSOLE_IN_EX_NOTIFY;
typedef struct {
UINTN Signature;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_EVENT DelayedRecoveryEvent;
EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleInput;
- EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleInputEx;
+ EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
EFI_USB_ENDPOINT_DESCRIPTOR IntEndpointDescriptor;
@@ -93,7 +104,23 @@ typedef struct {
EFI_EVENT RepeatTimer;
EFI_UNICODE_STRING_TABLE *ControllerNameTable;
-
+
+ UINT8 LeftCtrlOn;
+ UINT8 LeftAltOn;
+ UINT8 LeftShiftOn;
+ UINT8 LeftLogoOn;
+ UINT8 RightCtrlOn;
+ UINT8 RightAltOn;
+ UINT8 RightShiftOn;
+ UINT8 RightLogoOn;
+ UINT8 MenuKeyOn;
+ UINT8 SysReqOn;
+
+ EFI_KEY_STATE KeyState;
+ //
+ // Notification function list
+ //
+ LIST_ENTRY NotifyList;
} USB_KB_DEV;
//
@@ -103,6 +130,7 @@ extern EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL gUsbKeyboardComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gUsbKeyboardComponentName2;
extern EFI_GUID gEfiUsbKeyboardDriverGuid;
+extern EFI_GUID gSimpleTextInExNotifyGuid;
VOID
KbdReportStatusCode (
@@ -113,6 +141,9 @@ KbdReportStatusCode (
#define USB_KB_DEV_FROM_THIS(a) \
CR(a, USB_KB_DEV, SimpleInput, USB_KB_DEV_SIGNATURE)
+#define TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS(a) \
+ CR(a, USB_KB_DEV, SimpleInputEx, USB_KB_DEV_SIGNATURE)
+
#define MOD_CONTROL_L 0x01
#define MOD_CONTROL_R 0x10
@@ -128,7 +159,7 @@ typedef struct {
UINT8 Key;
} KB_MODIFIER;
-#define USB_KEYCODE_MAX_MAKE 0x64
+#define USB_KEYCODE_MAX_MAKE 0x7E
#define USBKBD_VALID_KEYCODE(key) ((UINT8) (key) > 3)
@@ -138,4 +169,137 @@ typedef struct {
UINT8 ScrollLock : 1;
UINT8 Resrvd : 5;
} LED_MAP;
+
+//
+// Simple Text Input Ex protocol functions
+//
+EFI_STATUS
+EFIAPI
+USBKeyboardResetEx (
+ 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
+USBKeyboardReadKeyStrokeEx (
+ 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
+USBKeyboardSetState (
+ 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
+USBKeyboardRegisterKeyNotify (
+ 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
+USBKeyboardUnregisterKeyNotify (
+ 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.
+
+--*/
+;
+
#endif
+
diff --git a/MdeModulePkg/Bus/Usb/UsbKbDxe/keyboard.c b/MdeModulePkg/Bus/Usb/UsbKbDxe/keyboard.c
index 9ad1bcef24..87179a4c6b 100644
--- a/MdeModulePkg/Bus/Usb/UsbKbDxe/keyboard.c
+++ b/MdeModulePkg/Bus/Usb/UsbKbDxe/keyboard.c
@@ -94,8 +94,8 @@ UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][3] = {
{ SCAN_F8, 0x00, 0x00 }, // 0x41
{ SCAN_F9, 0x00, 0x00 }, // 0x42
{ SCAN_F10, 0x00, 0x00 }, // 0x43
- { SCAN_F11, 0x00, 0x00 }, // 0x44 F11
- { SCAN_F12, 0x00, 0x00 }, // 0x45 F12
+ { SCAN_F11, 0x00, 0x00 }, // 0x44 F11
+ { SCAN_F12, 0x00, 0x00 }, // 0x45 F12
{ SCAN_NULL, 0x00, 0x00 }, // 0x46 PrintScreen
{ SCAN_NULL, 0x00, 0x00 }, // 0x47 Scroll Lock
{ SCAN_NULL, 0x00, 0x00 }, // 0x48 Pause
@@ -129,7 +129,22 @@ UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][3] = {
{ SCAN_NULL, '\\', '|' }, // 0x64 Keyboard Non-US \ and |
{ SCAN_NULL, 0x00, 0x00 }, // 0x65 Keyboard Application
{ SCAN_NULL, 0x00, 0x00 }, // 0x66 Keyboard Power
- { SCAN_NULL, '=' , '=' } // 0x67 Keypad =
+ { SCAN_NULL, '=' , '=' }, // 0x67 Keypad =
+ { SCAN_F13, 0x00, 0x00 }, // 0x68
+ { SCAN_F14, 0x00, 0x00 }, // 0x69
+ { SCAN_F15, 0x00, 0x00 }, // 0x6A
+ { SCAN_F16, 0x00, 0x00 }, // 0x6B
+ { SCAN_F17, 0x00, 0x00 }, // 0x6C
+ { SCAN_F18, 0x00, 0x00 }, // 0x6D
+ { SCAN_F19, 0x00, 0x00 }, // 0x6E
+ { SCAN_F20, 0x00, 0x00 }, // 0x6F
+ { SCAN_F21, 0x00, 0x00 }, // 0x70
+ { SCAN_F22, 0x00, 0x00 }, // 0x71
+ { SCAN_F23, 0x00, 0x00 }, // 0x72
+ { SCAN_F24, 0x00, 0x00 }, // 0x73
+ { SCAN_MUTE, 0x00, 0x00 }, // 0x7F
+ { SCAN_VOLUME_UP, 0x00, 0x00 }, // 0x80
+ { SCAN_VOLUME_DOWN, 0x00, 0x00 }, // 0x81
};
STATIC KB_MODIFIER KB_Mod[8] = {
@@ -140,7 +155,7 @@ STATIC KB_MODIFIER KB_Mod[8] = {
{ MOD_ALT_L, 0xe2 }, // 11100010
{ MOD_ALT_R, 0xe6 }, // 11100110
{ MOD_WIN_L, 0xe3 }, // 11100011
- { MOD_WIN_R, 0xe7 } // 11100111
+ { MOD_WIN_R, 0xe7 }, // 11100111
};
@@ -286,6 +301,17 @@ InitUSBKeyboard (
UsbKeyboardDevice->NumLockOn = 0;
UsbKeyboardDevice->CapsOn = 0;
UsbKeyboardDevice->ScrollOn = 0;
+
+ UsbKeyboardDevice->LeftCtrlOn = 0;
+ UsbKeyboardDevice->LeftAltOn = 0;
+ UsbKeyboardDevice->LeftShiftOn = 0;
+ UsbKeyboardDevice->LeftLogoOn = 0;
+ UsbKeyboardDevice->RightCtrlOn = 0;
+ UsbKeyboardDevice->RightAltOn = 0;
+ UsbKeyboardDevice->RightShiftOn = 0;
+ UsbKeyboardDevice->RightLogoOn = 0;
+ UsbKeyboardDevice->MenuKeyOn = 0;
+ UsbKeyboardDevice->SysReqOn = 0;
//
// Sync the initial state of lights
@@ -675,21 +701,65 @@ USBParseKey (
if (!UsbKey.Down) {
switch (UsbKey.KeyCode) {
+ //
+ // CTRL release
+ //
case 0xe0:
+ UsbKeyboardDevice->LeftCtrlOn = 0;
+ UsbKeyboardDevice->CtrlOn = 0;
+ break;
case 0xe4:
+ UsbKeyboardDevice->RightCtrlOn = 0;
UsbKeyboardDevice->CtrlOn = 0;
break;
+ //
+ // Shift release
+ //
case 0xe1:
+ UsbKeyboardDevice->LeftShiftOn = 0;
+ UsbKeyboardDevice->ShiftOn = 0;
+ break;
case 0xe5:
+ UsbKeyboardDevice->RightShiftOn = 0;
UsbKeyboardDevice->ShiftOn = 0;
break;
+ //
+ // Alt release
+ //
case 0xe2:
+ UsbKeyboardDevice->LeftAltOn = 0;
+ UsbKeyboardDevice->AltOn = 0;
+ break;
case 0xe6:
+ UsbKeyboardDevice->RightAltOn = 0;
UsbKeyboardDevice->AltOn = 0;
break;
+ //
+ // Logo release
+ //
+ case 0xe3:
+ UsbKeyboardDevice->LeftLogoOn = 0;
+ break;
+ case 0xe7:
+ UsbKeyboardDevice->RightLogoOn = 0;
+ break;
+
+ //
+ // Menu key (App/Apps) release
+ //
+ case 0x65:
+ UsbKeyboardDevice->MenuKeyOn = 0;
+ break;
+
+ //
+ // SysReq release
+ //
+ case 0x46:
+ UsbKeyboardDevice->SysReqOn = 0;
+ break;
default:
break;
}
@@ -703,51 +773,95 @@ USBParseKey (
switch (UsbKey.KeyCode) {
case 0xe0:
+ UsbKeyboardDevice->LeftCtrlOn = 1;
+ UsbKeyboardDevice->CtrlOn = 1;
+ continue;
+ break;
case 0xe4:
+ UsbKeyboardDevice->RightCtrlOn = 1;
UsbKeyboardDevice->CtrlOn = 1;
continue;
break;
+ //
+ // Shift press
+ //
case 0xe1:
+ UsbKeyboardDevice->LeftShiftOn = 1;
+ UsbKeyboardDevice->ShiftOn = 1;
+ continue;
+ break;
case 0xe5:
+ UsbKeyboardDevice->RightShiftOn = 1;
UsbKeyboardDevice->ShiftOn = 1;
continue;
break;
+ //
+ // Alt press
+ //
case 0xe2:
+ UsbKeyboardDevice->LeftAltOn = 1;
+ UsbKeyboardDevice->AltOn = 1;
+ continue;
+ break;
case 0xe6:
+ UsbKeyboardDevice->RightAltOn = 1;
UsbKeyboardDevice->AltOn = 1;
continue;
break;
+ //
+ // Logo press
+ //
case 0xe3:
+ UsbKeyboardDevice->LeftLogoOn = 1;
+ continue;
+ break;
case 0xe7:
+ UsbKeyboardDevice->RightLogoOn = 1;
continue;
break;
- case 0x53:
- UsbKeyboardDevice->NumLockOn ^= 1;
//
- // Turn on the NumLock light on KB
+ // Menu key (App/Apps) press
+ //
+ case 0x65:
+ UsbKeyboardDevice->MenuKeyOn = 1;
+ continue;
+ break;
+
+ //
+ // SysReq press
//
+ case 0x46:
+ UsbKeyboardDevice->SysReqOn = 1;
+ continue;
+ break;
+
+ case 0x53:
+ UsbKeyboardDevice->NumLockOn ^= 1;
+ //
+ // Turn on the NumLock light on KB
+ //
SetKeyLED (UsbKeyboardDevice);
continue;
break;
case 0x39:
UsbKeyboardDevice->CapsOn ^= 1;
- //
- // Turn on the CapsLock light on KB
- //
+ //
+ // Turn on the CapsLock light on KB
+ //
SetKeyLED (UsbKeyboardDevice);
continue;
break;
case 0x47:
UsbKeyboardDevice->ScrollOn ^= 1;
- //
- // Turn on the ScrollLock light on KB
- //
+ //
+ // Turn on the ScrollLock light on KB
+ //
SetKeyLED (UsbKeyboardDevice);
continue;
break;
@@ -757,18 +871,14 @@ USBParseKey (
// keys are not valid EFI key
//
- case 0x46:
- //
- // fall through
//
+ // PrintScreen/SysRq key and Application key
+ // Should be handled by UEFI2.1 compliant code
+
case 0x48:
//
// fall through
//
- case 0x65:
- //
- // fall through
- //
case 0x66:
//
// fall through
@@ -834,11 +944,26 @@ USBKeyCodeToEFIScanCode (
return EFI_NOT_READY;
}
+ //
+ // Undefined entries from 0x74 to 0x7E
+ //
+ if (KeyChar > USB_KEYCODE_MAX_MAKE) {
+ Index = (UINT8) (Index - 11);
+ }
+
Key->ScanCode = KeyConvertionTable[Index][0];
if (UsbKeyboardDevice->ShiftOn) {
Key->UnicodeChar = KeyConvertionTable[Index][2];
+ //
+ // Need not return associated shift state if a class of printable characters that
+ // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
+ //
+ if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {
+ UsbKeyboardDevice->LeftShiftOn = 0;
+ UsbKeyboardDevice->RightShiftOn = 0;
+ }
} else {
@@ -885,6 +1010,51 @@ USBKeyCodeToEFIScanCode (
return EFI_NOT_READY;
}
+
+ //
+ // Save Shift/Toggle state
+ //
+ if (UsbKeyboardDevice->LeftCtrlOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
+ }
+ if (UsbKeyboardDevice->RightCtrlOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
+ }
+ if (UsbKeyboardDevice->LeftAltOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;
+ }
+ if (UsbKeyboardDevice->RightAltOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
+ }
+ if (UsbKeyboardDevice->LeftShiftOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
+ }
+ if (UsbKeyboardDevice->RightShiftOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
+ }
+ if (UsbKeyboardDevice->LeftLogoOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
+ }
+ if (UsbKeyboardDevice->RightLogoOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
+ }
+ if (UsbKeyboardDevice->MenuKeyOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;
+ }
+ if (UsbKeyboardDevice->SysReqOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;
+ }
+
+ if (UsbKeyboardDevice->ScrollOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
+ }
+ if (UsbKeyboardDevice->NumLockOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
+ }
+ if (UsbKeyboardDevice->CapsOn == 1) {
+ UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
+ }
+
return EFI_SUCCESS;
}
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,
@@ -1513,6 +1591,66 @@ Returns:
}
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,
IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer
@@ -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 <Protocol/SimpleTextOut.h>
#include <Guid/ConsoleInDevice.h>
#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextInEx.h>
#include <Protocol/ConsoleControl.h>
#include <Guid/StandardErrorDevice.h>
#include <Guid/ConsoleOutDevice.h>
@@ -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 <Guid/GlobalVariable.h>
#include <Protocol/DevicePath.h>
#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextInEx.h>
#include <Guid/HotPlugDevice.h>
#include <Guid/PcAnsi.h>
#include <Library/DebugLib.h>
@@ -42,7 +43,7 @@ Revision History
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DevicePathLib.h>
#include <Library/PcdLib.h>
-
+#include <Library/BaseLib.h>
#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. <BR>
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]