/** @file\r
ConsoleOut Routines that speak VGA.\r
\r
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
\r
BiosKeyboardPrivate->Queue.Front = 0;\r
BiosKeyboardPrivate->Queue.Rear = 0;\r
+ BiosKeyboardPrivate->QueueForNotify.Front = 0;\r
+ BiosKeyboardPrivate->QueueForNotify.Rear = 0;\r
BiosKeyboardPrivate->SimpleTextInputEx.Reset = BiosKeyboardResetEx;\r
BiosKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx = BiosKeyboardReadKeyStrokeEx;\r
BiosKeyboardPrivate->SimpleTextInputEx.SetState = BiosKeyboardSetState;\r
StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;\r
goto Done;\r
}\r
- \r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ KeyNotifyProcessHandler,\r
+ BiosKeyboardPrivate,\r
+ &BiosKeyboardPrivate->KeyNotifyProcessEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;\r
+ goto Done;\r
+ }\r
+\r
//\r
// Report a Progress Code for an attempt to detect the precense of the keyboard device in the system\r
//\r
if ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) {\r
gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx); \r
}\r
+\r
+ if (BiosKeyboardPrivate->KeyNotifyProcessEvent != NULL) {\r
+ gBS->CloseEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);\r
+ }\r
+\r
BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);\r
\r
if (BiosKeyboardPrivate->TimerEvent != NULL) {\r
gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey);\r
gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent);\r
gBS->CloseEvent (BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx);\r
+ gBS->CloseEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);\r
BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);\r
\r
FreePool (BiosKeyboardPrivate);\r
}\r
\r
//\r
- // Invoke notification functions if exist\r
+ // Signal KeyNotify process event if this key pressed matches any key registered.\r
//\r
for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {\r
CurrentNotify = CR (\r
NotifyEntry, \r
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
);\r
- if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { \r
- CurrentNotify->KeyNotificationFn (&KeyData);\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+ //\r
+ // The key notification function needs to run at TPL_CALLBACK\r
+ // while current TPL is TPL_NOTIFY. It will be invoked in\r
+ // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.\r
+ //\r
+ Enqueue (&BiosKeyboardPrivate->QueueForNotify, &KeyData);\r
+ gBS->SignalEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);\r
}\r
}\r
\r
return ; \r
}\r
\r
+/**\r
+ Process key notify.\r
+\r
+ @param Event Indicates the event that invoke this function.\r
+ @param Context Indicates the calling context.\r
+**/\r
+VOID\r
+EFIAPI\r
+KeyNotifyProcessHandler (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+ EFI_KEY_DATA KeyData;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NotifyList;\r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+ EFI_TPL OldTpl;\r
+\r
+ BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) Context;\r
+\r
+ //\r
+ // Invoke notification functions.\r
+ //\r
+ NotifyList = &BiosKeyboardPrivate->NotifyList;\r
+ while (TRUE) {\r
+ //\r
+ // Enter critical section\r
+ // \r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ Status = Dequeue (&BiosKeyboardPrivate->QueueForNotify, &KeyData);\r
+ //\r
+ // Leave critical section\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {\r
+ CurrentNotify = CR (Link, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+ CurrentNotify->KeyNotificationFn (&KeyData);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
/**\r
Free keyboard notify list.\r
\r