}\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 = GetFirstNode (&ConsoleIn->NotifyList); !IsNull (&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, Link)) {\r
CurrentNotify = CR (\r
KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
);\r
if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
- CurrentNotify->KeyNotificationFn (&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
+ PushEfikeyBufTail (&ConsoleIn->EfiKeyQueueForNotify, &KeyData);\r
+ gBS->SignalEvent (ConsoleIn->KeyNotifyProcessEvent);\r
}\r
}\r
\r
ConsoleIn->ScancodeQueue.Tail = 0;\r
ConsoleIn->EfiKeyQueue.Head = 0;\r
ConsoleIn->EfiKeyQueue.Tail = 0;\r
+ ConsoleIn->EfiKeyQueueForNotify.Head = 0;\r
+ ConsoleIn->EfiKeyQueueForNotify.Tail = 0;\r
\r
//\r
// Reset the status indicators\r
return Status;\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
+ KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
+ EFI_KEY_DATA KeyData;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NotifyList;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+ EFI_TPL OldTpl;\r
+\r
+ ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;\r
+\r
+ //\r
+ // Invoke notification functions.\r
+ //\r
+ NotifyList = &ConsoleIn->NotifyList;\r
+ while (TRUE) {\r
+ //\r
+ // Enter critical section\r
+ // \r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ Status = PopEfikeyBufHead (&ConsoleIn->EfiKeyQueueForNotify, &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, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+ CurrentNotify->KeyNotificationFn (&KeyData);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
goto ErrorExit;\r
}\r
\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ KeyNotifyProcessHandler,\r
+ ConsoleIn,\r
+ &ConsoleIn->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 ErrorExit;\r
+ }\r
+\r
REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
EFI_PROGRESS_CODE,\r
EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,\r
if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) {\r
gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);\r
}\r
+ if ((ConsoleIn != NULL) && (ConsoleIn->KeyNotifyProcessEvent != NULL)) {\r
+ gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);\r
+ }\r
KbdFreeNotifyList (&ConsoleIn->NotifyList);\r
if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {\r
FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);\r
gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);\r
ConsoleIn->ConInEx.WaitForKeyEx = NULL;\r
}\r
+ if (ConsoleIn->KeyNotifyProcessEvent != NULL) {\r
+ gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);\r
+ ConsoleIn->KeyNotifyProcessEvent = NULL;\r
+ }\r
KbdFreeNotifyList (&ConsoleIn->NotifyList);\r
FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);\r
gBS->FreePool (ConsoleIn);\r
//\r
SCAN_CODE_QUEUE ScancodeQueue;\r
EFI_KEY_QUEUE EfiKeyQueue;\r
+ EFI_KEY_QUEUE EfiKeyQueueForNotify;\r
\r
//\r
// Error state\r
// Notification Function List\r
//\r
LIST_ENTRY NotifyList;\r
+ EFI_EVENT KeyNotifyProcessEvent;\r
} KEYBOARD_CONSOLE_IN_DEV;\r
\r
#define KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a) CR (a, KEYBOARD_CONSOLE_IN_DEV, ConIn, KEYBOARD_CONSOLE_IN_DEV_SIGNATURE)\r
IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\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
/**\r
Perform 8042 controller and keyboard Initialization.\r
If ExtendedVerification is TRUE, do additional test for\r