USB Keyboard Driver that manages USB keyboard and produces Simple Text Input\r
Protocol and Simple Text Input Ex Protocol.\r
\r
-Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
\r
if (!Found) {\r
//\r
+ // Report Status Code to indicate that there is no USB keyboard\r
+ //\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED)\r
+ );\r
+ //\r
// No interrupt endpoint found, then return unsupported.\r
//\r
Status = EFI_UNSUPPORTED;\r
goto ErrorExit;\r
}\r
\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED),\r
+ UsbKeyboardDevice->DevicePath\r
+ );\r
+\r
UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;\r
UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;\r
UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;\r
goto ErrorExit;\r
}\r
\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ KeyNotifyProcessHandler,\r
+ UsbKeyboardDevice,\r
+ &UsbKeyboardDevice->KeyNotifyProcessEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorExit;\r
+ }\r
+\r
//\r
// Install Simple Text Input Protocol and Simple Text Input Ex Protocol\r
// for the USB keyboard device.\r
if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
}\r
+ if (UsbKeyboardDevice->KeyNotifyProcessEvent != NULL) {\r
+ gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);\r
+ }\r
if (UsbKeyboardDevice->KeyboardLayoutEvent != NULL) {\r
ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
+ gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);\r
KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);\r
\r
ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
\r
DestroyQueue (&UsbKeyboardDevice->UsbKeyQueue);\r
DestroyQueue (&UsbKeyboardDevice->EfiKeyQueue);\r
+ DestroyQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify);\r
\r
FreePool (UsbKeyboardDevice);\r
\r
//\r
InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY));\r
InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA));\r
+ InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA));\r
\r
return EFI_SUCCESS;\r
}\r
if (KeyData.Key.ScanCode == CHAR_NULL && KeyData.Key.UnicodeChar == SCAN_NULL) {\r
continue;\r
}\r
+ //\r
+ // Translate the CTRL-Alpha characters to their corresponding control value\r
+ // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)\r
+ //\r
+ if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
+ if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {\r
+ KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);\r
+ } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {\r
+ KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);\r
+ }\r
+ }\r
+\r
CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
return EFI_SUCCESS;\r
}\r
Register a notification function for a particular keystroke for the input device.\r
\r
@param This Protocol instance pointer.\r
- @param KeyData A pointer to a buffer that is filled in with the keystroke\r
- information data for the key that was pressed.\r
+ @param KeyData A pointer to a buffer that is filled in with\r
+ the keystroke information for the key that was\r
+ pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState\r
+ and KeyData.KeyState.KeyShiftState are 0, then any incomplete\r
+ keystroke will trigger a notification of the KeyNotificationFunction.\r
@param KeyNotificationFunction Points to the function to be called when the key\r
- sequence is typed specified by KeyData.\r
+ sequence is typed specified by KeyData. This notification function\r
+ should be called at <=TPL_CALLBACK.\r
@param NotifyHandle Points to the unique handle assigned to the registered notification.\r
\r
@retval EFI_SUCCESS The notification function was registered successfully.\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
+ OUT VOID **NotifyHandle\r
)\r
{\r
USB_KB_DEV *UsbKeyboardDevice;\r
);\r
if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
- *NotifyHandle = CurrentNotify->NotifyHandle;\r
+ *NotifyHandle = CurrentNotify;\r
return EFI_SUCCESS;\r
}\r
}\r
\r
NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
- NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;\r
CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);\r
\r
\r
- *NotifyHandle = NewNotify->NotifyHandle;\r
+ *NotifyHandle = NewNotify;\r
\r
return EFI_SUCCESS;\r
\r
EFIAPI\r
USBKeyboardUnregisterKeyNotify (\r
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
- IN EFI_HANDLE NotificationHandle\r
+ IN VOID *NotificationHandle\r
)\r
{\r
USB_KB_DEV *UsbKeyboardDevice;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
\r
//\r
NotifyEntry,\r
USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
);\r
- if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+ if (CurrentNotify == NotificationHandle) {\r
//\r
// Remove the notification function from NotifyList and free resources\r
//\r
return EFI_INVALID_PARAMETER;\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
+ USB_KB_DEV *UsbKeyboardDevice;\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
+ UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
+\r
+ //\r
+ // Invoke notification functions.\r
+ //\r
+ NotifyList = &UsbKeyboardDevice->NotifyList;\r
+ while (TRUE) {\r
+ //\r
+ // Enter critical section\r
+ // \r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ Status = Dequeue (&UsbKeyboardDevice->EfiKeyQueueForNotify, &KeyData, sizeof (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, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+ CurrentNotify->KeyNotificationFn (&KeyData);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r