+\r
+STATIC\r
+BOOLEAN\r
+IsKeyRegistered (\r
+ IN EFI_KEY_DATA *RegsiteredData,\r
+ IN EFI_KEY_DATA *InputData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+ RegsiteredData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was registered.\r
+ InputData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+Returns:\r
+ TRUE - Key be pressed matches a registered key.\r
+ FLASE - Match failed. \r
+ \r
+--*/\r
+{\r
+ ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+ \r
+ if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
+ return FALSE; \r
+ } \r
+ \r
+ //\r
+ // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
+ //\r
+ if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
+ RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
+ return FALSE; \r
+ } \r
+ if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
+ RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
+ return FALSE; \r
+ } \r
+ \r
+ return TRUE;\r
+\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+KeyboardWaitForKeyEx (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event\r
+ Signal the event if there is key available\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
+\r
+ ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (Context); \r
+ KeyboardWaitForKey (Event, &ConsoleInDev->ConIn);\r
+ \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+KeyboardEfiResetEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reset the input device and optionaly run diagnostics\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device was reset.\r
+ EFI_DEVICE_ERROR - The device is not functioning properly and could \r
+ not be reset.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
+ EFI_TPL OldTpl;\r
+\r
+ ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); \r
+ if (ConsoleInDev->KeyboardErr) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Status = ConsoleInDev->ConIn.Reset (\r
+ &ConsoleInDev->ConIn, \r
+ ExtendedVerification\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ ConsoleInDev->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
+ ConsoleInDev->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
+\r
+ gBS->RestoreTPL (OldTpl); \r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+KeyboardReadKeyStrokeEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The keystroke information was returned.\r
+ EFI_NOT_READY - There was no keystroke data availiable.\r
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
+ hardware errors.\r
+ EFI_INVALID_PARAMETER - KeyData is NULL. \r
+\r
+--*/\r
+{\r
+ KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
+\r
+ if (KeyData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
+ return KeyboardReadKeyStrokeWorker (ConsoleInDev, KeyData);\r
+ \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+KeyboardSetState (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Set certain state for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+ state for the input device.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device state was set successfully.\r
+ EFI_DEVICE_ERROR - The device is not functioning correctly and could \r
+ not have the setting adjusted.\r
+ EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
+ EFI_INVALID_PARAMETER - KeyToggleState is NULL. \r
+\r
+--*/ \r
+{\r
+ EFI_STATUS Status;\r
+ KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
+ EFI_TPL OldTpl;\r
+\r
+ if (KeyToggleState == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
+\r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ if (ConsoleInDev->KeyboardErr) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if (((ConsoleInDev->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||\r
+ ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Exit;\r
+ }\r
+ \r
+ //\r
+ // Update the status light\r
+ //\r
+ ConsoleInDev->ScrollLock = FALSE;\r
+ ConsoleInDev->NumLock = FALSE;\r
+ ConsoleInDev->CapsLock = FALSE;\r
+\r
+ if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
+ ConsoleInDev->ScrollLock = TRUE;\r
+ } \r
+ if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
+ ConsoleInDev->NumLock = TRUE;\r
+ }\r
+ if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
+ ConsoleInDev->CapsLock = TRUE;\r
+ }\r
+\r
+ Status = UpdateStatusLights (ConsoleInDev);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR; \r
+ }\r
+\r
+ ConsoleInDev->KeyState.KeyToggleState = *KeyToggleState;\r
+ \r
+Exit: \r
+ //\r
+ // Leave critical section and return\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+\r
+}\r
+EFI_STATUS\r
+EFIAPI\r
+KeyboardRegisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_DATA *KeyData,\r
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Register a notification function for a particular keystroke for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ information data for the key that was pressed.\r
+ KeyNotificationFunction - Points to the function to be called when the key \r
+ sequence is typed specified by KeyData. \r
+ NotifyHandle - Points to the unique handle assigned to the registered notification. \r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was registered successfully.\r
+ EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
+ EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. \r
+ \r
+--*/ \r
+{\r
+ EFI_STATUS Status;\r
+ KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
+ EFI_TPL OldTpl;\r
+ LIST_ENTRY *Link;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
+\r
+ if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
+\r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+\r
+ //\r
+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
+ //\r
+ for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ );\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+ if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+ *NotifyHandle = CurrentNotify->NotifyHandle; \r
+ Status = EFI_SUCCESS;\r
+ goto Exit;\r
+ }\r
+ }\r
+ } \r
+ \r
+ //\r
+ // Allocate resource to save the notification function\r
+ // \r
+ NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
+ if (NewNotify == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ NewNotify->Signature = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE; \r
+ NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
+ InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);\r
+\r
+ //\r
+ // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
+ // \r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &NewNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ *NotifyHandle = NewNotify->NotifyHandle; \r
+ Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+ //\r
+ // Leave critical section and return\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status; \r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+KeyboardUnregisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Remove a registered notification function from a particular keystroke.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer. \r
+ NotificationHandle - The handle of the notification function being unregistered.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was unregistered successfully.\r
+ EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
+ EFI_NOT_FOUND - Can not find the matching entry in database. \r
+ \r
+--*/ \r
+{\r
+ EFI_STATUS Status;\r
+ KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
+ EFI_TPL OldTpl;\r
+ LIST_ENTRY *Link;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
+\r
+ if (NotificationHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+ \r
+ Status = gBS->OpenProtocol (\r
+ NotificationHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
+ \r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY); \r
+\r
+ for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
+ NotifyEntry, \r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+ ); \r
+ if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+ //\r
+ // Remove the notification function from NotifyList and free resources\r
+ //\r
+ RemoveEntryList (&CurrentNotify->NotifyEntry); \r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ CurrentNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ gBS->FreePool (CurrentNotify); \r
+ Status = EFI_SUCCESS;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Can not find the specified Notification Handle\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+Exit:\r
+ //\r
+ // Leave critical section and return\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r