/** 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); } } } }
/** Reads the next keystroke from the input device. The WaitForKey Event can be used to test for existance of a keystroke via WaitForEvent () call. @param ConsoleInDev Ps2 Keyboard private structure @param KeyData A pointer to a buffer that is filled in with the keystroke state data for the key that was pressed. @retval EFI_SUCCESS The keystroke information was returned. @retval EFI_NOT_READY There was no keystroke data availiable. @retval EFI_DEVICE_ERROR The keystroke information was not returned due to hardware errors. @retval EFI_INVALID_PARAMETER KeyData is NULL. **/ EFI_STATUS KeyboardReadKeyStrokeWorker ( IN KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev, OUT EFI_KEY_DATA *KeyData ) { EFI_STATUS Status; EFI_TPL OldTpl; LIST_ENTRY *Link; KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; EFI_KEY_DATA OriginalKeyData; if (KeyData == NULL) { return EFI_INVALID_PARAMETER; } // // Enter critical section // OldTpl = gBS->RaiseTPL (TPL_NOTIFY); if (ConsoleInDev->KeyboardErr) { gBS->RestoreTPL (OldTpl); return EFI_DEVICE_ERROR; } // // If there's no key, just return // Status = KeyboardCheckForKey (&ConsoleInDev->ConIn); if (EFI_ERROR (Status)) { gBS->RestoreTPL (OldTpl); return EFI_NOT_READY; } CopyMem (&KeyData->Key, &ConsoleInDev->Key, sizeof (EFI_INPUT_KEY)); ConsoleInDev->Key.ScanCode = SCAN_NULL; ConsoleInDev->Key.UnicodeChar = 0x0000; CopyMem (&KeyData->KeyState, &ConsoleInDev->KeyState, sizeof (EFI_KEY_STATE)); ConsoleInDev->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID; ConsoleInDev->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID; gBS->RestoreTPL (OldTpl); // //Switch the control value to their original characters. In KeyGetchar() 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 (ConsoleInDev->Ctrled) { if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) { if (ConsoleInDev->CapsLock) { OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + L'A' - 1); } else { OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + L'a' - 1); } } } // // Invoke notification functions if exist // for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) { CurrentNotify = CR ( Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE ); if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) { CurrentNotify->KeyNotificationFn (&OriginalKeyData); } } return EFI_SUCCESS; }