2 USB Keyboard Driver that manages USB keyboard and produces Simple Text Input
3 Protocol and Simple Text Input Ex Protocol.
5 Copyright (c) 2004 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 // USB Keyboard Driver Global Variables
22 EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding
= {
23 USBKeyboardDriverBindingSupported
,
24 USBKeyboardDriverBindingStart
,
25 USBKeyboardDriverBindingStop
,
32 Entrypoint of USB Keyboard Driver.
34 This function is the entrypoint of USB Keyboard Driver. It installs Driver Binding
35 Protocols together with Component Name Protocols.
37 @param ImageHandle The firmware allocated handle for the EFI image.
38 @param SystemTable A pointer to the EFI System Table.
40 @retval EFI_SUCCESS The entry point is executed successfully.
45 USBKeyboardDriverBindingEntryPoint (
46 IN EFI_HANDLE ImageHandle
,
47 IN EFI_SYSTEM_TABLE
*SystemTable
52 Status
= EfiLibInstallDriverBindingComponentName2 (
55 &gUsbKeyboardDriverBinding
,
57 &gUsbKeyboardComponentName
,
58 &gUsbKeyboardComponentName2
60 ASSERT_EFI_ERROR (Status
);
66 Check whether USB keyboard driver supports this device.
68 @param This The USB keyboard driver binding protocol.
69 @param Controller The controller handle to check.
70 @param RemainingDevicePath The remaining device path.
72 @retval EFI_SUCCESS The driver supports this controller.
73 @retval other This device isn't supported.
78 USBKeyboardDriverBindingSupported (
79 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
80 IN EFI_HANDLE Controller
,
81 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
85 EFI_USB_IO_PROTOCOL
*UsbIo
;
88 // Check if USB I/O Protocol is attached on the controller handle.
90 Status
= gBS
->OpenProtocol (
92 &gEfiUsbIoProtocolGuid
,
94 This
->DriverBindingHandle
,
96 EFI_OPEN_PROTOCOL_BY_DRIVER
98 if (EFI_ERROR (Status
)) {
103 // Use the USB I/O Protocol interface to check whether Controller is
104 // a keyboard device that can be managed by this driver.
106 Status
= EFI_SUCCESS
;
108 if (!IsUSBKeyboard (UsbIo
)) {
109 Status
= EFI_UNSUPPORTED
;
114 &gEfiUsbIoProtocolGuid
,
115 This
->DriverBindingHandle
,
123 Starts the keyboard device with this driver.
125 This function produces Simple Text Input Protocol and Simple Text Input Ex Protocol,
126 initializes the keyboard device, and submit Asynchronous Interrupt Transfer to manage
127 this keyboard device.
129 @param This The USB keyboard driver binding instance.
130 @param Controller Handle of device to bind driver to.
131 @param RemainingDevicePath Optional parameter use to pick a specific child
134 @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver.
135 @retval EFI_UNSUPPORTED No interrupt endpoint can be found.
136 @retval Other This controller cannot be started.
141 USBKeyboardDriverBindingStart (
142 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
143 IN EFI_HANDLE Controller
,
144 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
148 EFI_USB_IO_PROTOCOL
*UsbIo
;
149 USB_KB_DEV
*UsbKeyboardDevice
;
150 UINT8 EndpointNumber
;
151 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
154 UINT8 PollingInterval
;
159 // Open USB I/O Protocol
161 Status
= gBS
->OpenProtocol (
163 &gEfiUsbIoProtocolGuid
,
165 This
->DriverBindingHandle
,
167 EFI_OPEN_PROTOCOL_BY_DRIVER
169 if (EFI_ERROR (Status
)) {
173 UsbKeyboardDevice
= AllocateZeroPool (sizeof (USB_KB_DEV
));
174 ASSERT (UsbKeyboardDevice
!= NULL
);
177 // Get the Device Path Protocol on Controller's handle
179 Status
= gBS
->OpenProtocol (
181 &gEfiDevicePathProtocolGuid
,
182 (VOID
**) &UsbKeyboardDevice
->DevicePath
,
183 This
->DriverBindingHandle
,
185 EFI_OPEN_PROTOCOL_GET_PROTOCOL
188 if (EFI_ERROR (Status
)) {
192 // Report that the USB keyboard is being enabled
194 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
196 PcdGet32 (PcdStatusCodeValueKeyboardEnable
),
197 UsbKeyboardDevice
->DevicePath
201 // This is pretty close to keyboard detection, so log progress
203 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
205 PcdGet32 (PcdStatusCodeValueKeyboardPresenceDetect
),
206 UsbKeyboardDevice
->DevicePath
209 UsbKeyboardDevice
->UsbIo
= UsbIo
;
212 // Get interface & endpoint descriptor
214 UsbIo
->UsbGetInterfaceDescriptor (
216 &UsbKeyboardDevice
->InterfaceDescriptor
219 EndpointNumber
= UsbKeyboardDevice
->InterfaceDescriptor
.NumEndpoints
;
222 // Traverse endpoints to find interrupt endpoint
225 for (Index
= 0; Index
< EndpointNumber
; Index
++) {
227 UsbIo
->UsbGetEndpointDescriptor (
233 if ((EndpointDescriptor
.Attributes
& (BIT0
| BIT1
)) == USB_ENDPOINT_INTERRUPT
) {
235 // We only care interrupt endpoint here
237 CopyMem(&UsbKeyboardDevice
->IntEndpointDescriptor
, &EndpointDescriptor
, sizeof(EndpointDescriptor
));
245 // No interrupt endpoint found, then return unsupported.
247 Status
= EFI_UNSUPPORTED
;
251 UsbKeyboardDevice
->Signature
= USB_KB_DEV_SIGNATURE
;
252 UsbKeyboardDevice
->SimpleInput
.Reset
= USBKeyboardReset
;
253 UsbKeyboardDevice
->SimpleInput
.ReadKeyStroke
= USBKeyboardReadKeyStroke
;
255 UsbKeyboardDevice
->SimpleInputEx
.Reset
= USBKeyboardResetEx
;
256 UsbKeyboardDevice
->SimpleInputEx
.ReadKeyStrokeEx
= USBKeyboardReadKeyStrokeEx
;
257 UsbKeyboardDevice
->SimpleInputEx
.SetState
= USBKeyboardSetState
;
258 UsbKeyboardDevice
->SimpleInputEx
.RegisterKeyNotify
= USBKeyboardRegisterKeyNotify
;
259 UsbKeyboardDevice
->SimpleInputEx
.UnregisterKeyNotify
= USBKeyboardUnregisterKeyNotify
;
261 InitializeListHead (&UsbKeyboardDevice
->NotifyList
);
263 Status
= gBS
->CreateEvent (
266 USBKeyboardWaitForKey
,
268 &(UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
)
271 if (EFI_ERROR (Status
)) {
275 Status
= gBS
->CreateEvent (
278 USBKeyboardWaitForKey
,
280 &(UsbKeyboardDevice
->SimpleInput
.WaitForKey
)
283 if (EFI_ERROR (Status
)) {
287 Status
= InitKeyboardLayout (UsbKeyboardDevice
);
288 if (EFI_ERROR (Status
)) {
293 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol
294 // for the USB keyboard device.
295 // USB keyboard is a hot plug device, and expected to work immediately
296 // when plugging into system, other conventional console devices could
297 // distinguish it by its device path.
299 Status
= gBS
->InstallMultipleProtocolInterfaces (
301 &gEfiSimpleTextInProtocolGuid
,
302 &UsbKeyboardDevice
->SimpleInput
,
303 &gEfiSimpleTextInputExProtocolGuid
,
304 &UsbKeyboardDevice
->SimpleInputEx
,
307 if (EFI_ERROR (Status
)) {
312 // Reset USB Keyboard Device exhaustively.
314 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (
315 &UsbKeyboardDevice
->SimpleInput
,
318 if (EFI_ERROR (Status
)) {
319 gBS
->UninstallMultipleProtocolInterfaces (
321 &gEfiSimpleTextInProtocolGuid
,
322 &UsbKeyboardDevice
->SimpleInput
,
323 &gEfiSimpleTextInputExProtocolGuid
,
324 &UsbKeyboardDevice
->SimpleInputEx
,
331 // Submit Asynchronous Interrupt Transfer to manage this device.
333 EndpointAddr
= UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
;
334 PollingInterval
= UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
;
335 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
337 Status
= UsbIo
->UsbAsyncInterruptTransfer (
347 if (EFI_ERROR (Status
)) {
348 gBS
->UninstallMultipleProtocolInterfaces (
350 &gEfiSimpleTextInProtocolGuid
,
351 &UsbKeyboardDevice
->SimpleInput
,
352 &gEfiSimpleTextInputExProtocolGuid
,
353 &UsbKeyboardDevice
->SimpleInputEx
,
359 UsbKeyboardDevice
->ControllerNameTable
= NULL
;
362 gUsbKeyboardComponentName
.SupportedLanguages
,
363 &UsbKeyboardDevice
->ControllerNameTable
,
364 L
"Generic Usb Keyboard",
369 gUsbKeyboardComponentName2
.SupportedLanguages
,
370 &UsbKeyboardDevice
->ControllerNameTable
,
371 L
"Generic Usb Keyboard",
381 if (UsbKeyboardDevice
!= NULL
) {
382 if (UsbKeyboardDevice
->SimpleInput
.WaitForKey
!= NULL
) {
383 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
385 if (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
386 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
388 FreePool (UsbKeyboardDevice
);
389 UsbKeyboardDevice
= NULL
;
393 &gEfiUsbIoProtocolGuid
,
394 This
->DriverBindingHandle
,
403 Stop the USB keyboard device handled by this driver.
405 @param This The USB keyboard driver binding protocol.
406 @param Controller The controller to release.
407 @param NumberOfChildren The number of handles in ChildHandleBuffer.
408 @param ChildHandleBuffer The array of child handle.
410 @retval EFI_SUCCESS The device was stopped.
411 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol
412 is not installed on Controller.
413 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
414 @retval Others Fail to uninstall protocols attached on the device.
419 USBKeyboardDriverBindingStop (
420 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
421 IN EFI_HANDLE Controller
,
422 IN UINTN NumberOfChildren
,
423 IN EFI_HANDLE
*ChildHandleBuffer
427 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleInput
;
428 USB_KB_DEV
*UsbKeyboardDevice
;
430 Status
= gBS
->OpenProtocol (
432 &gEfiSimpleTextInProtocolGuid
,
433 (VOID
**) &SimpleInput
,
434 This
->DriverBindingHandle
,
436 EFI_OPEN_PROTOCOL_GET_PROTOCOL
438 if (EFI_ERROR (Status
)) {
439 return EFI_UNSUPPORTED
;
442 Status
= gBS
->OpenProtocol (
444 &gEfiSimpleTextInputExProtocolGuid
,
446 This
->DriverBindingHandle
,
448 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
450 if (EFI_ERROR (Status
)) {
451 return EFI_UNSUPPORTED
;
454 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (SimpleInput
);
457 // The key data input from this device will be disabled.
459 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
461 PcdGet32 (PcdStatusCodeValueKeyboardDisable
),
462 UsbKeyboardDevice
->DevicePath
466 // Delete the Asynchronous Interrupt Transfer from this device
468 UsbKeyboardDevice
->UsbIo
->UsbAsyncInterruptTransfer (
469 UsbKeyboardDevice
->UsbIo
,
470 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
472 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,
480 &gEfiUsbIoProtocolGuid
,
481 This
->DriverBindingHandle
,
485 Status
= gBS
->UninstallMultipleProtocolInterfaces (
487 &gEfiSimpleTextInProtocolGuid
,
488 &UsbKeyboardDevice
->SimpleInput
,
489 &gEfiSimpleTextInputExProtocolGuid
,
490 &UsbKeyboardDevice
->SimpleInputEx
,
494 // Free all resources.
496 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
497 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
498 gBS
->CloseEvent ((UsbKeyboardDevice
->SimpleInput
).WaitForKey
);
499 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
500 KbdFreeNotifyList (&UsbKeyboardDevice
->NotifyList
);
502 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
503 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
505 if (UsbKeyboardDevice
->ControllerNameTable
!= NULL
) {
506 FreeUnicodeStringTable (UsbKeyboardDevice
->ControllerNameTable
);
509 FreePool (UsbKeyboardDevice
);
515 Internal function to read the next keystroke from the keyboard buffer.
517 @param UsbKeyboardDevice USB keyboard's private structure.
518 @param KeyData A pointer to buffer to hold the keystroke
519 data for the key that was pressed.
521 @retval EFI_SUCCESS The keystroke information was returned.
522 @retval EFI_NOT_READY There was no keystroke data availiable.
523 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
525 @retval EFI_INVALID_PARAMETER KeyData is NULL.
526 @retval Others Fail to translate keycode into EFI_INPUT_KEY
531 USBKeyboardReadKeyStrokeWorker (
532 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
533 OUT EFI_KEY_DATA
*KeyData
539 LIST_ENTRY
*NotifyList
;
540 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
541 EFI_KEY_DATA OriginalKeyData
;
543 if (KeyData
== NULL
) {
544 return EFI_INVALID_PARAMETER
;
548 // If there is no saved USB keycode, fetch it
549 // by calling USBKeyboardCheckForKey().
551 if (UsbKeyboardDevice
->CurKeyCode
== 0) {
552 Status
= USBKeyboardCheckForKey (UsbKeyboardDevice
);
553 if (EFI_ERROR (Status
)) {
554 return EFI_NOT_READY
;
558 KeyData
->Key
.UnicodeChar
= 0;
559 KeyData
->Key
.ScanCode
= SCAN_NULL
;
562 // Store the current keycode and clear it.
564 KeyCode
= UsbKeyboardDevice
->CurKeyCode
;
565 UsbKeyboardDevice
->CurKeyCode
= 0;
568 // Translate saved USB keycode into EFI_INPUT_KEY
570 Status
= UsbKeyCodeToEfiInputKey (UsbKeyboardDevice
, KeyCode
, &KeyData
->Key
);
571 if (EFI_ERROR (Status
)) {
576 // Get current state of various toggled attributes as well as input modifier values,
577 // and set them as valid.
579 CopyMem (&KeyData
->KeyState
, &UsbKeyboardDevice
->KeyState
, sizeof (KeyData
->KeyState
));
581 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
582 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
585 // Switch the control value to their original characters.
586 // In UsbKeyCodeToEfiInputKey() the CTRL-Alpha characters have been switched to
587 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A),
588 // here switch them back for notification function.
590 CopyMem (&OriginalKeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
591 if (UsbKeyboardDevice
->CtrlOn
) {
592 if (OriginalKeyData
.Key
.UnicodeChar
>= 0x01 && OriginalKeyData
.Key
.UnicodeChar
<= 0x1A) {
593 if (UsbKeyboardDevice
->CapsOn
) {
594 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'A' - 1);
596 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'a' - 1);
602 // Invoke notification functions if the key is registered.
604 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
605 for (Link
= GetFirstNode (NotifyList
);
606 !IsNull (NotifyList
, Link
);
607 Link
= GetNextNode (NotifyList
, Link
)) {
608 CurrentNotify
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
609 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &OriginalKeyData
)) {
610 CurrentNotify
->KeyNotificationFn (&OriginalKeyData
);
618 Reset the input device and optionally run diagnostics
620 There are 2 types of reset for USB keyboard.
621 For non-exhaustive reset, only keyboard buffer is cleared.
622 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status
623 is also re-initialized.
625 @param This Protocol instance pointer.
626 @param ExtendedVerification Driver may perform diagnostics on reset.
628 @retval EFI_SUCCESS The device was reset.
629 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
635 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
636 IN BOOLEAN ExtendedVerification
640 USB_KB_DEV
*UsbKeyboardDevice
;
642 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
644 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
646 PcdGet32 (PcdStatusCodeValueKeyboardReset
),
647 UsbKeyboardDevice
->DevicePath
651 // Non-exhaustive reset:
652 // only reset private data structures.
654 if (!ExtendedVerification
) {
655 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
657 PcdGet32 (PcdStatusCodeValueKeyboardClearBuffer
),
658 UsbKeyboardDevice
->DevicePath
661 // Clear the key buffer of this USB keyboard
663 InitUSBKeyBuffer (&(UsbKeyboardDevice
->KeyboardBuffer
));
664 UsbKeyboardDevice
->CurKeyCode
= 0;
672 Status
= InitUSBKeyboard (UsbKeyboardDevice
);
673 UsbKeyboardDevice
->CurKeyCode
= 0;
674 if (EFI_ERROR (Status
)) {
675 return EFI_DEVICE_ERROR
;
683 Reads the next keystroke from the input device.
685 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
686 @param Key A pointer to a buffer that is filled in with the keystroke
687 information for the key that was pressed.
689 @retval EFI_SUCCESS The keystroke information was returned.
690 @retval EFI_NOT_READY There was no keystroke data availiable.
691 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
697 USBKeyboardReadKeyStroke (
698 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
699 OUT EFI_INPUT_KEY
*Key
702 USB_KB_DEV
*UsbKeyboardDevice
;
704 EFI_KEY_DATA KeyData
;
706 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
708 Status
= USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, &KeyData
);
709 if (EFI_ERROR (Status
)) {
713 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
720 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx
721 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.
723 @param Event Event to be signaled when a key is pressed.
724 @param Context Points to USB_KB_DEV instance.
729 USBKeyboardWaitForKey (
734 USB_KB_DEV
*UsbKeyboardDevice
;
736 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
738 if (UsbKeyboardDevice
->CurKeyCode
== 0) {
739 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice
))) {
741 // If no pending key, simply return.
747 // If there is pending key, signal the event.
749 gBS
->SignalEvent (Event
);
754 Check whether there is key pending in the keyboard buffer.
756 @param UsbKeyboardDevice The USB_KB_DEV instance.
758 @retval EFI_SUCCESS There is pending key to read.
759 @retval EFI_NOT_READY No pending key to read.
764 USBKeyboardCheckForKey (
765 IN OUT USB_KB_DEV
*UsbKeyboardDevice
772 // Fetch raw data from the USB keyboard buffer,
773 // and translate it into USB keycode.
775 Status
= USBParseKey (UsbKeyboardDevice
, &KeyCode
);
776 if (EFI_ERROR (Status
)) {
777 return EFI_NOT_READY
;
780 UsbKeyboardDevice
->CurKeyCode
= KeyCode
;
785 Free keyboard notify list.
787 @param NotifyList The keyboard notify list to free.
789 @retval EFI_SUCCESS Free the notify list successfully.
790 @retval EFI_INVALID_PARAMETER NotifyList is NULL.
796 IN OUT LIST_ENTRY
*NotifyList
799 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
802 if (NotifyList
== NULL
) {
803 return EFI_INVALID_PARAMETER
;
805 while (!IsListEmpty (NotifyList
)) {
806 Link
= GetFirstNode (NotifyList
);
807 NotifyNode
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
808 RemoveEntryList (Link
);
809 FreePool (NotifyNode
);
816 Check whether the pressed key matches a registered key or not.
818 @param RegsiteredData A pointer to keystroke data for the key that was registered.
819 @param InputData A pointer to keystroke data for the key that was pressed.
821 @retval TRUE Key pressed matches a registered key.
822 @retval FLASE Key pressed does not matches a registered key.
828 IN EFI_KEY_DATA
*RegsiteredData
,
829 IN EFI_KEY_DATA
*InputData
832 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
834 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
835 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
840 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
842 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
843 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
846 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
847 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
855 // Simple Text Input Ex protocol functions
858 Resets the input device hardware.
860 The Reset() function resets the input device hardware. As part
861 of initialization process, the firmware/device will make a quick
862 but reasonable attempt to verify that the device is functioning.
863 If the ExtendedVerification flag is TRUE the firmware may take
864 an extended amount of time to verify the device is operating on
865 reset. Otherwise the reset operation is to occur as quickly as
866 possible. The hardware verification process is not defined by
867 this specification and is left up to the platform firmware or
870 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
872 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
873 verification operation of the device during reset.
875 @retval EFI_SUCCESS The device was reset.
876 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
882 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
883 IN BOOLEAN ExtendedVerification
887 USB_KB_DEV
*UsbKeyboardDevice
;
891 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
893 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (&UsbKeyboardDevice
->SimpleInput
, ExtendedVerification
);
894 if (EFI_ERROR (Status
)) {
895 return EFI_DEVICE_ERROR
;
898 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
899 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
900 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
901 gBS
->RestoreTPL (OldTpl
);
908 Reads the next keystroke from the input device.
910 @param This Protocol instance pointer.
911 @param KeyData A pointer to a buffer that is filled in with the keystroke
912 state data for the key that was pressed.
914 @retval EFI_SUCCESS The keystroke information was returned.
915 @retval EFI_NOT_READY There was no keystroke data available.
916 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
918 @retval EFI_INVALID_PARAMETER KeyData is NULL.
923 USBKeyboardReadKeyStrokeEx (
924 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
925 OUT EFI_KEY_DATA
*KeyData
928 USB_KB_DEV
*UsbKeyboardDevice
;
930 if (KeyData
== NULL
) {
931 return EFI_INVALID_PARAMETER
;
934 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
936 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, KeyData
);
941 Set certain state for the input device.
943 @param This Protocol instance pointer.
944 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
945 state for the input device.
947 @retval EFI_SUCCESS The device state was set appropriately.
948 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
949 not have the setting adjusted.
950 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.
951 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
956 USBKeyboardSetState (
957 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
958 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
961 USB_KB_DEV
*UsbKeyboardDevice
;
963 if (KeyToggleState
== NULL
) {
964 return EFI_INVALID_PARAMETER
;
967 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
969 if (((UsbKeyboardDevice
->KeyState
.KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) ||
970 ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
)) {
971 return EFI_UNSUPPORTED
;
975 // Update the status light
978 UsbKeyboardDevice
->ScrollOn
= FALSE
;
979 UsbKeyboardDevice
->NumLockOn
= FALSE
;
980 UsbKeyboardDevice
->CapsOn
= FALSE
;
982 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
983 UsbKeyboardDevice
->ScrollOn
= TRUE
;
985 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
986 UsbKeyboardDevice
->NumLockOn
= TRUE
;
988 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
989 UsbKeyboardDevice
->CapsOn
= TRUE
;
992 SetKeyLED (UsbKeyboardDevice
);
994 UsbKeyboardDevice
->KeyState
.KeyToggleState
= *KeyToggleState
;
1001 Register a notification function for a particular keystroke for the input device.
1003 @param This Protocol instance pointer.
1004 @param KeyData A pointer to a buffer that is filled in with the keystroke
1005 information data for the key that was pressed.
1006 @param KeyNotificationFunction Points to the function to be called when the key
1007 sequence is typed specified by KeyData.
1008 @param NotifyHandle Points to the unique handle assigned to the registered notification.
1010 @retval EFI_SUCCESS The notification function was registered successfully.
1011 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.
1012 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
1017 USBKeyboardRegisterKeyNotify (
1018 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1019 IN EFI_KEY_DATA
*KeyData
,
1020 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
1021 OUT EFI_HANDLE
*NotifyHandle
1024 USB_KB_DEV
*UsbKeyboardDevice
;
1025 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
1027 LIST_ENTRY
*NotifyList
;
1028 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1030 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
1031 return EFI_INVALID_PARAMETER
;
1034 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1037 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1039 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1041 for (Link
= GetFirstNode (NotifyList
);
1042 !IsNull (NotifyList
, Link
);
1043 Link
= GetNextNode (NotifyList
, Link
)) {
1044 CurrentNotify
= CR (
1046 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1048 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1050 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
1051 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
1052 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
1059 // Allocate resource to save the notification function
1061 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
1062 if (NewNotify
== NULL
) {
1063 return EFI_OUT_OF_RESOURCES
;
1066 NewNotify
->Signature
= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
1067 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
1068 NewNotify
->NotifyHandle
= (EFI_HANDLE
) NewNotify
;
1069 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
1070 InsertTailList (&UsbKeyboardDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
1073 *NotifyHandle
= NewNotify
->NotifyHandle
;
1080 Remove a registered notification function from a particular keystroke.
1082 @param This Protocol instance pointer.
1083 @param NotificationHandle The handle of the notification function being unregistered.
1085 @retval EFI_SUCCESS The notification function was unregistered successfully.
1086 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid
1087 @retval EFI_NOT_FOUND Cannot find the matching entry in database.
1092 USBKeyboardUnregisterKeyNotify (
1093 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1094 IN EFI_HANDLE NotificationHandle
1097 USB_KB_DEV
*UsbKeyboardDevice
;
1098 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1100 LIST_ENTRY
*NotifyList
;
1102 if (NotificationHandle
== NULL
) {
1103 return EFI_INVALID_PARAMETER
;
1106 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1109 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.
1111 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1112 for (Link
= GetFirstNode (NotifyList
);
1113 !IsNull (NotifyList
, Link
);
1114 Link
= GetNextNode (NotifyList
, Link
)) {
1115 CurrentNotify
= CR (
1117 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1119 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1121 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
1123 // Remove the notification function from NotifyList and free resources
1125 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
1127 FreePool (CurrentNotify
);
1132 return EFI_NOT_FOUND
;