X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FBus%2FUsb%2FUsbKbDxe%2FEfiKey.c;h=ccb389067a615142bb48d655a6304d5d1c8fa3cd;hb=f9c2c71ed69ca1d92687a55d3ef947cfb4413b3e;hp=eb9bbd971f63ecf9770d98cb5cf6a961265f9505;hpb=ea0210023728e57519584432ac5cb6c11869b93d;p=mirror_edk2.git diff --git a/MdeModulePkg/Bus/Usb/UsbKbDxe/EfiKey.c b/MdeModulePkg/Bus/Usb/UsbKbDxe/EfiKey.c index eb9bbd971f..ccb389067a 100644 --- a/MdeModulePkg/Bus/Usb/UsbKbDxe/EfiKey.c +++ b/MdeModulePkg/Bus/Usb/UsbKbDxe/EfiKey.c @@ -2,14 +2,8 @@ USB Keyboard Driver that manages USB keyboard and produces Simple Text Input Protocol and Simple Text Input Ex Protocol. -Copyright (c) 2004 - 2010, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -154,7 +148,9 @@ USBKeyboardDriverBindingStart ( UINT8 PollingInterval; UINT8 PacketSize; BOOLEAN Found; + EFI_TPL OldTpl; + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); // // Open USB I/O Protocol // @@ -167,7 +163,7 @@ USBKeyboardDriverBindingStart ( EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { - return Status; + goto ErrorExit1; } UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV)); @@ -219,7 +215,7 @@ USBKeyboardDriverBindingStart ( EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints; // - // Traverse endpoints to find interrupt endpoint + // Traverse endpoints to find interrupt endpoint IN // Found = FALSE; for (Index = 0; Index < EndpointNumber; Index++) { @@ -230,7 +226,8 @@ USBKeyboardDriverBindingStart ( &EndpointDescriptor ); - if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) { + if (((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) && + ((EndpointDescriptor.EndpointAddress & USB_ENDPOINT_DIR_IN) != 0)) { // // We only care interrupt endpoint here // @@ -242,12 +239,25 @@ USBKeyboardDriverBindingStart ( if (!Found) { // + // Report Status Code to indicate that there is no USB keyboard + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED) + ); + // // No interrupt endpoint found, then return unsupported. // Status = EFI_UNSUPPORTED; goto ErrorExit; } + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED), + UsbKeyboardDevice->DevicePath + ); + UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE; UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset; UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke; @@ -257,9 +267,23 @@ USBKeyboardDriverBindingStart ( UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState; UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify; UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify; - + InitializeListHead (&UsbKeyboardDevice->NotifyList); - + + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + USBKeyboardTimerHandler, + UsbKeyboardDevice, + &UsbKeyboardDevice->TimerEvent + ); + if (!EFI_ERROR (Status)) { + Status = gBS->SetTimer (UsbKeyboardDevice->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL); + } + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, @@ -283,6 +307,17 @@ USBKeyboardDriverBindingStart ( goto ErrorExit; } + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + KeyNotifyProcessHandler, + UsbKeyboardDevice, + &UsbKeyboardDevice->KeyNotifyProcessEvent + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + // // Install Simple Text Input Protocol and Simple Text Input Ex Protocol // for the USB keyboard device. @@ -320,8 +355,8 @@ USBKeyboardDriverBindingStart ( // // Reset USB Keyboard Device exhaustively. // - Status = UsbKeyboardDevice->SimpleInput.Reset ( - &UsbKeyboardDevice->SimpleInput, + Status = UsbKeyboardDevice->SimpleInputEx.Reset ( + &UsbKeyboardDevice->SimpleInputEx, TRUE ); if (EFI_ERROR (Status)) { @@ -381,6 +416,7 @@ USBKeyboardDriverBindingStart ( FALSE ); + gBS->RestoreTPL (OldTpl); return EFI_SUCCESS; // @@ -388,12 +424,18 @@ USBKeyboardDriverBindingStart ( // ErrorExit: if (UsbKeyboardDevice != NULL) { + if (UsbKeyboardDevice->TimerEvent != NULL) { + gBS->CloseEvent (UsbKeyboardDevice->TimerEvent); + } if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) { gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey); } if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) { gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx); } + if (UsbKeyboardDevice->KeyNotifyProcessEvent != NULL) { + gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent); + } if (UsbKeyboardDevice->KeyboardLayoutEvent != NULL) { ReleaseKeyboardLayoutResources (UsbKeyboardDevice); gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent); @@ -407,6 +449,10 @@ ErrorExit: This->DriverBindingHandle, Controller ); + +ErrorExit1: + gBS->RestoreTPL (OldTpl); + return Status; } @@ -506,11 +552,13 @@ USBKeyboardDriverBindingStop ( // // Free all resources. // + gBS->CloseEvent (UsbKeyboardDevice->TimerEvent); gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer); gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent); - gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey); - gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx); - KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList); + gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey); + gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx); + gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent); + KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList); ReleaseKeyboardLayoutResources (UsbKeyboardDevice); gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent); @@ -519,6 +567,10 @@ USBKeyboardDriverBindingStop ( FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable); } + DestroyQueue (&UsbKeyboardDevice->UsbKeyQueue); + DestroyQueue (&UsbKeyboardDevice->EfiKeyQueue); + DestroyQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify); + FreePool (UsbKeyboardDevice); return Status; @@ -540,89 +592,22 @@ USBKeyboardDriverBindingStop ( **/ EFI_STATUS -EFIAPI USBKeyboardReadKeyStrokeWorker ( IN OUT USB_KB_DEV *UsbKeyboardDevice, OUT EFI_KEY_DATA *KeyData ) { - EFI_STATUS Status; - UINT8 KeyCode; - LIST_ENTRY *Link; - LIST_ENTRY *NotifyList; - KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; - EFI_KEY_DATA OriginalKeyData; - if (KeyData == NULL) { return EFI_INVALID_PARAMETER; } - // - // If there is no saved USB keycode, fetch it - // by calling USBKeyboardCheckForKey(). - // - if (UsbKeyboardDevice->CurKeyCode == 0) { - Status = USBKeyboardCheckForKey (UsbKeyboardDevice); - if (EFI_ERROR (Status)) { - return EFI_NOT_READY; - } - } - - KeyData->Key.UnicodeChar = 0; - KeyData->Key.ScanCode = SCAN_NULL; - - // - // Store the current keycode and clear it. - // - KeyCode = UsbKeyboardDevice->CurKeyCode; - UsbKeyboardDevice->CurKeyCode = 0; - - // - // Translate saved USB keycode into EFI_INPUT_KEY - // - Status = UsbKeyCodeToEfiInputKey (UsbKeyboardDevice, KeyCode, &KeyData->Key); - if (EFI_ERROR (Status)) { - return Status; + if (IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) { + ZeroMem (&KeyData->Key, sizeof (KeyData->Key)); + InitializeKeyState (UsbKeyboardDevice, &KeyData->KeyState); + return EFI_NOT_READY; } - // - // Get current state of various toggled attributes as well as input modifier values, - // and set them as valid. - // - 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 UsbKeyCodeToEfiInputKey() 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 the key is registered. - // - NotifyList = &UsbKeyboardDevice->NotifyList; - for (Link = GetFirstNode (NotifyList); - !IsNull (NotifyList, Link); - Link = GetNextNode (NotifyList, Link)) { - CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE); - if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) { - CurrentNotify->KeyNotificationFn (&OriginalKeyData); - } - } + Dequeue (&UsbKeyboardDevice->EfiKeyQueue, KeyData, sizeof (*KeyData)); return EFI_SUCCESS; } @@ -673,8 +658,9 @@ USBKeyboardReset ( // // Clear the key buffer of this USB keyboard // - InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer)); - UsbKeyboardDevice->CurKeyCode = 0; + InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY)); + InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA)); + InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA)); return EFI_SUCCESS; } @@ -683,7 +669,6 @@ USBKeyboardReset ( // Exhaustive reset // Status = InitUSBKeyboard (UsbKeyboardDevice); - UsbKeyboardDevice->CurKeyCode = 0; if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -718,14 +703,37 @@ USBKeyboardReadKeyStroke ( UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This); - Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData); - if (EFI_ERROR (Status)) { - return Status; - } - - CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); + // + // Considering if the partial keystroke is enabled, there maybe a partial + // keystroke in the queue, so here skip the partial keystroke and get the + // next key from the queue + // + while (1) { + Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData); + if (EFI_ERROR (Status)) { + return Status; + } + // + // SimpleTextIn Protocol doesn't support partial keystroke; + // + if (KeyData.Key.ScanCode == CHAR_NULL && KeyData.Key.UnicodeChar == SCAN_NULL) { + continue; + } + // + // Translate the CTRL-Alpha characters to their corresponding control value + // (ctrl-a = 0x0001 through ctrl-Z = 0x001A) + // + if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) { + if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') { + KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1); + } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') { + KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1); + } + } - return EFI_SUCCESS; + CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); + return EFI_SUCCESS; + } } @@ -745,41 +753,63 @@ USBKeyboardWaitForKey ( ) { USB_KB_DEV *UsbKeyboardDevice; + EFI_KEY_DATA KeyData; + EFI_TPL OldTpl; UsbKeyboardDevice = (USB_KB_DEV *) Context; - if (UsbKeyboardDevice->CurKeyCode == 0) { - if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice))) { - // - // If no pending key, simply return. - // - return ; + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // WaitforKey doesn't suppor the partial key. + // Considering if the partial keystroke is enabled, there maybe a partial + // keystroke in the queue, so here skip the partial keystroke and get the + // next key from the queue + // + while (!IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) { + // + // If there is pending key, signal the event. + // + CopyMem ( + &KeyData, + UsbKeyboardDevice->EfiKeyQueue.Buffer[UsbKeyboardDevice->EfiKeyQueue.Head], + sizeof (EFI_KEY_DATA) + ); + if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { + Dequeue (&UsbKeyboardDevice->EfiKeyQueue, &KeyData, sizeof (EFI_KEY_DATA)); + continue; } + gBS->SignalEvent (Event); + break; } // - // If there is pending key, signal the event. + // Leave critical section and return // - gBS->SignalEvent (Event); + gBS->RestoreTPL (OldTpl); } - /** - Check whether there is key pending in the keyboard buffer. - - @param UsbKeyboardDevice The USB_KB_DEV instance. - - @retval EFI_SUCCESS There is pending key to read. - @retval EFI_NOT_READY No pending key to read. + Timer handler to convert the key from USB. + @param Event Indicates the event that invoke this function. + @param Context Indicates the calling context. **/ -EFI_STATUS +VOID EFIAPI -USBKeyboardCheckForKey ( - IN OUT USB_KB_DEV *UsbKeyboardDevice +USBKeyboardTimerHandler ( + IN EFI_EVENT Event, + IN VOID *Context ) { - EFI_STATUS Status; - UINT8 KeyCode; + EFI_STATUS Status; + USB_KB_DEV *UsbKeyboardDevice; + UINT8 KeyCode; + EFI_KEY_DATA KeyData; + + UsbKeyboardDevice = (USB_KB_DEV *) Context; // // Fetch raw data from the USB keyboard buffer, @@ -787,11 +817,21 @@ USBKeyboardCheckForKey ( // Status = USBParseKey (UsbKeyboardDevice, &KeyCode); if (EFI_ERROR (Status)) { - return EFI_NOT_READY; + return ; } - UsbKeyboardDevice->CurKeyCode = KeyCode; - return EFI_SUCCESS; + // + // Translate saved USB keycode into EFI_INPUT_KEY + // + Status = UsbKeyCodeToEfiInputKey (UsbKeyboardDevice, KeyCode, &KeyData); + if (EFI_ERROR (Status)) { + return ; + } + + // + // Insert to the EFI Key queue + // + Enqueue (&UsbKeyboardDevice->EfiKeyQueue, &KeyData, sizeof (KeyData)); } /** @@ -804,7 +844,6 @@ USBKeyboardCheckForKey ( **/ EFI_STATUS -EFIAPI KbdFreeNotifyList ( IN OUT LIST_ENTRY *NotifyList ) @@ -821,7 +860,7 @@ KbdFreeNotifyList ( RemoveEntryList (Link); FreePool (NotifyNode); } - + return EFI_SUCCESS; } @@ -836,36 +875,35 @@ KbdFreeNotifyList ( **/ BOOLEAN -EFIAPI IsKeyRegistered ( IN EFI_KEY_DATA *RegsiteredData, IN EFI_KEY_DATA *InputData ) { ASSERT (RegsiteredData != NULL && InputData != NULL); - + if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) || (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) { - return FALSE; - } - + 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; - } + return FALSE; + } if (RegsiteredData->KeyState.KeyToggleState != 0 && RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) { - return FALSE; - } - + return FALSE; + } + return TRUE; } // -// Simple Text Input Ex protocol functions +// Simple Text Input Ex protocol functions // /** Resets the input device hardware. @@ -898,8 +936,6 @@ USBKeyboardResetEx ( { EFI_STATUS Status; USB_KB_DEV *UsbKeyboardDevice; - EFI_TPL OldTpl; - UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This); @@ -908,10 +944,8 @@ USBKeyboardResetEx ( 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; @@ -947,7 +981,7 @@ USBKeyboardReadKeyStrokeEx ( UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This); return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData); - + } /** @@ -991,7 +1025,8 @@ USBKeyboardSetState ( UsbKeyboardDevice->ScrollOn = FALSE; UsbKeyboardDevice->NumLockOn = FALSE; UsbKeyboardDevice->CapsOn = FALSE; - + UsbKeyboardDevice->IsSupportPartialKey = FALSE; + if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) { UsbKeyboardDevice->ScrollOn = TRUE; } @@ -1001,23 +1036,30 @@ USBKeyboardSetState ( if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) { UsbKeyboardDevice->CapsOn = TRUE; } + if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) { + UsbKeyboardDevice->IsSupportPartialKey = TRUE; + } SetKeyLED (UsbKeyboardDevice); UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState; return EFI_SUCCESS; - + } /** Register a notification function for a particular keystroke for the input device. @param This Protocol instance pointer. - @param KeyData A pointer to a buffer that is filled in with the keystroke - information data for the key that was pressed. + @param KeyData A pointer to a buffer that is filled in with + the keystroke information for the key that was + pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState + and KeyData.KeyState.KeyShiftState are 0, then any incomplete + keystroke will trigger a notification of the KeyNotificationFunction. @param KeyNotificationFunction Points to the function to be called when the key - sequence is typed specified by KeyData. + sequence is typed specified by KeyData. This notification function + should be called at <=TPL_CALLBACK. @param NotifyHandle Points to the unique handle assigned to the registered notification. @retval EFI_SUCCESS The notification function was registered successfully. @@ -1031,14 +1073,14 @@ USBKeyboardRegisterKeyNotify ( IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, IN EFI_KEY_DATA *KeyData, IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, - OUT EFI_HANDLE *NotifyHandle + OUT VOID **NotifyHandle ) { USB_KB_DEV *UsbKeyboardDevice; KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify; LIST_ENTRY *Link; LIST_ENTRY *NotifyList; - KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) { return EFI_INVALID_PARAMETER; @@ -1050,43 +1092,42 @@ USBKeyboardRegisterKeyNotify ( // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. // NotifyList = &UsbKeyboardDevice->NotifyList; - + for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) { CurrentNotify = CR ( - Link, - KEYBOARD_CONSOLE_IN_EX_NOTIFY, - NotifyEntry, + Link, + KEYBOARD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE ); - if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { - *NotifyHandle = CurrentNotify->NotifyHandle; + *NotifyHandle = CurrentNotify; 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->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE; NewNotify->KeyNotificationFn = KeyNotificationFunction; - NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify; CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA)); InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry); - *NotifyHandle = NewNotify->NotifyHandle; - + *NotifyHandle = NewNotify; + return EFI_SUCCESS; - + } /** @@ -1103,7 +1144,7 @@ EFI_STATUS EFIAPI USBKeyboardUnregisterKeyNotify ( IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN EFI_HANDLE NotificationHandle + IN VOID *NotificationHandle ) { USB_KB_DEV *UsbKeyboardDevice; @@ -1113,14 +1154,10 @@ USBKeyboardUnregisterKeyNotify ( if (NotificationHandle == NULL) { return EFI_INVALID_PARAMETER; - } + } - if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE) { - return EFI_INVALID_PARAMETER; - } - UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This); - + // // Traverse notify list of USB keyboard and remove the entry of NotificationHandle. // @@ -1129,18 +1166,18 @@ USBKeyboardUnregisterKeyNotify ( !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) { CurrentNotify = CR ( - Link, - KEYBOARD_CONSOLE_IN_EX_NOTIFY, - NotifyEntry, + Link, + KEYBOARD_CONSOLE_IN_EX_NOTIFY, + NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE - ); - if (CurrentNotify->NotifyHandle == NotificationHandle) { + ); + if (CurrentNotify == NotificationHandle) { // // Remove the notification function from NotifyList and free resources // - RemoveEntryList (&CurrentNotify->NotifyEntry); + RemoveEntryList (&CurrentNotify->NotifyEntry); - FreePool (CurrentNotify); + FreePool (CurrentNotify); return EFI_SUCCESS; } } @@ -1148,6 +1185,55 @@ USBKeyboardUnregisterKeyNotify ( // // Cannot find the matching entry in database. // - return EFI_INVALID_PARAMETER; + return EFI_INVALID_PARAMETER; +} + +/** + Process key notify. + + @param Event Indicates the event that invoke this function. + @param Context Indicates the calling context. +**/ +VOID +EFIAPI +KeyNotifyProcessHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + USB_KB_DEV *UsbKeyboardDevice; + EFI_KEY_DATA KeyData; + LIST_ENTRY *Link; + LIST_ENTRY *NotifyList; + KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; + EFI_TPL OldTpl; + + UsbKeyboardDevice = (USB_KB_DEV *) Context; + + // + // Invoke notification functions. + // + NotifyList = &UsbKeyboardDevice->NotifyList; + while (TRUE) { + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + Status = Dequeue (&UsbKeyboardDevice->EfiKeyQueueForNotify, &KeyData, sizeof (KeyData)); + // + // Leave critical section + // + gBS->RestoreTPL (OldTpl); + if (EFI_ERROR (Status)) { + break; + } + for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) { + CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE); + if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { + CurrentNotify->KeyNotificationFn (&KeyData); + } + } + } }